All answers

React Native

What does "Minified React error #31" mean?

The full message is "Objects are not valid as a React child." Something you render, such as a whole record, a Date, or an error object, isn't text or an element, so render one of its fields or turn it into a string. If the keys listed are {$$typeof, type, key, ref, props}, your app has mismatched React versions.

Updated October 31, 2026

A production build only shows a number for this error, which makes it look more mysterious than it is. React’s production builds leave out the full error messages to keep the download small, and error #31 is “Objects are not valid as a React child (found: %s). If you meant to render a collection of children, use an array instead.” The args[] part of the URL in your error fills in that %s, and it’s the best clue you have.

What it means

React can show text, numbers, elements, and arrays of those, but not a plain object. When an object ends up between the tags of a component, rendering stops with this error. Decode the args[] value (it’s URL-encoded, so %20 is a space and %7B is {) and match it to one of these:

  • object with keys {id, name, ...} means you rendered a whole record, like {user} instead of {user.name}. The listed keys tell you which record.
  • [object Date] means you rendered a Date. Format it first, for example with date.toLocaleDateString().
  • object with keys {$$typeof, type, key, ref, props} is a different problem. That’s the shape of an element created by React 19, and the old reactjs.org/docs/error-decoder.html link in the message comes from React 18 or earlier. So an element from one version of React reached another, which happens when react and react-dom are on different major versions, or a package brings its own copy of React.
  • [object Promise] shows up in React 18 and earlier when an async function’s result is rendered directly. Await it in an effect and render the stored result instead.

How to fix it

  1. Get the full message. Run the app in development, where the error shows in full along with the component that rendered the object. React’s docs recommend the development build for debugging, since it also tracks extra debug info and shows helpful warnings.

  2. Render a field, not the object:

    // Before
    <Text>{user}</Text>
    <Text>{error}</Text>
    
    // After
    <Text>{user.name}</Text>
    <Text>{error.message}</Text>
  3. Turn lists into elements with map, so each item becomes something React can show:

    {
      items.map((item) => <Text key={item.id}>{item.name}</Text>);
    }
  4. Check what your data really looks like when you’re not sure. Temporarily rendering JSON.stringify(value) shows the shape, including a field that’s an object when you expected a string.

  5. For the $$typeof case, line up your React versions. Run npm ls react react-dom to see every copy installed. In an Expo app, npx expo install --check lists packages that don’t match your SDK, and npx expo install --fix updates them.

How you know it’s fixed

The screen renders in development without the error, and a fresh production build shows the same screen instead of error #31.

If it still happens

Look for data whose shape changes. A field you expect to be a string can arrive as an object, such as a related record your query now includes or an error object your API returns in place of a message. That’s why we’d convert values once where the data comes in, so the rest of the app only ever sees strings and numbers.

Ask the agent

If your app is in Draftbit, paste this into the agent, and it can read your code and make the change for you.

My app shows Minified React error #31 in production. Run it in development to get the full message, find where we render an object, Date, or error directly, and render the right field or a formatted string instead. Also check that react and react-dom are on matching versions.

Open Draftbit

More React Native answers