React Error 310 Production

React Error #310: Minified React error in production β€” Fixed

React Error #310: Minified React error β€” Objects are not valid as React child

What is a Minified React Error?

In production builds, React replaces its full error messages with numeric codes to reduce bundle size. When React throws an error in production, you see something like:

Uncaught Error: Minified React error #310; visit
https://react.dev/errors/310 for the full message
or use the non-minified dev environment for full errors.

Error #310 decodes to: "Objects are not valid as a React child (found: object with keys {X, Y, …}). If you meant to render a collection of children, use an array instead."

In short: you are passing a plain JavaScript object directly into JSX where React expects a renderable value (string, number, array, or React element).

How to decode any Minified React Error

Go to react.dev/errors/310 and replace 310 with your error number. The page shows the full human-readable message with argument substitutions.

A faster approach: reproduce the crash in development mode. The dev bundle always throws the full descriptive error.

Cause 1: Rendering an object directly in JSX (double-brace trap)

In Vue you use double curly braces {{ }}. In React, a single pair of { } evaluates a JavaScript expression. Using double braces {{ obj }} creates an object literal { obj: value } and tries to render it β€” which React rejects.

❌ Causes Error #310 β€” object rendered as JSX child

// ❌ BAD: this renders the entire `user` object, not a string
const user = { name: 'Alice', role: 'admin' };

export default function Profile() {
  return (
    <div>
      <p>{user}</p>         {/* Error #310 β€” object is not a valid React child */}
      <p>{{ name: 'Bob' }}</p> {/* Same β€” double-brace creates an object literal */}
    </div>
  );
}

βœ… Correct β€” access a primitive property

const user = { name: 'Alice', role: 'admin' };

export default function Profile() {
  return (
    <div>
      <p>{user.name}</p>     {/* βœ… "Alice" β€” a string is a valid child */}
      <p>{user.role}</p>     {/* βœ… "admin" */}
    </div>
  );
}

Cause 2: Rendering a Promise or unresolved async value

If you call an async function and try to render the returned Promise directly, React sees an object (the Promise) β€” Error #310.

❌ Causes Error #310 β€” Promise rendered as child

async function fetchUsername(): Promise<string> {
  const res = await fetch('/api/me');
  return res.json().then(d => d.name);
}

export default function App() {
  // fetchUsername() returns a Promise<string>, not a string
  return <p>{fetchUsername()}</p>;  // ❌ Error #310
}

βœ… Correct β€” resolve with useEffect + useState

import { useState, useEffect } from 'react';

export default function App() {
  const [name, setName] = useState<string | null>(null);

  useEffect(() => {
    fetch('/api/me')
      .then(r => r.json())
      .then(d => setName(d.name));
  }, []);

  return <p>{name ?? 'Loading…'}</p>;  // βœ… string or null rendered safely
}

Cause 3: Rendering a Date object or other built-in objects

Date, Map, Set, Error β€” all objects. React cannot render them.

❌ Causes Error #310

const now = new Date();
return <time>{now}</time>;         // ❌ Date object, not a string

βœ… Correct β€” convert to string first

const now = new Date();
return <time>{now.toLocaleString()}</time>;   // βœ… string
return <time>{now.toISOString()}</time>;       // βœ… string

How to debug Error #310 in production

βœ… Step 1 β€” Add a source map to your production build

# Next.js: enable source maps in next.config.ts
const nextConfig = {
  productionBrowserSourceMaps: true,  // generates .map files in production
};
export default nextConfig;

# Now the browser stack trace will point to your real component file + line number

βœ… Step 2 β€” Wrap suspect renders in JSON.stringify for debugging

// If you're not sure what `data` is at runtime, log its type first:
console.log(typeof data, data);

// Temporary render check β€” never ship this:
return <pre>{JSON.stringify(data, null, 2)}</pre>;

Frequently Asked Questions

I only see this in production β€” it works in development. Why?

React's production build minifies error messages but the underlying logic is identical. If it works in dev, you likely have a race condition: data that is undefined in dev resolves before the first render, but in production (faster build, CDN, no dev server delay) the component renders before data is ready. Guard with if (!data) return null or a loading skeleton before accessing properties.

The error decoder URL leads to a generic page β€” how do I get the specific message?

Copy the full error URL from the console: https://react.dev/errors/310?args[]=.... The query params are the runtime arguments substituted into the message. If the URL is truncated, reproduce the error locally in development mode β€” React prints the complete message in console.error output.

Can TypeScript prevent Error #310?

Yes, partially. If your component prop types are strict (children: React.ReactNode does not accept object), TypeScript will catch accidental object rendering at compile time. Enable "strict": true in tsconfig.json and avoid any for data coming from APIs β€” use typed response schemas with Zod or similar instead.