Your agent added a line that shows a date, an API response, or a user record inside JSX. The page goes blank and the console says Objects are not valid as a React child (found: ...). The data is there and the component looks fine. React is refusing to turn one specific value into something it can draw.
Why this happens
The error text is fixed in React’s own error decoder: “Objects are not valid as a React child (found: %s). If you meant to render a collection of children, use an array instead.” The %s is filled in with what React found, which is the useful part of the message.
JSX can display strings and numbers, other elements, and arrays of those. It cannot display a plain object, because there is no single way to turn { id: 4, name: "Sam" } into text. When you write {user} instead of {user.name}, React gets the whole object and throws.
AI agents trigger this in a few predictable ways:
- Rendering a whole record such as
{user}or{order}instead of one field. - Rendering a
Datesuch as{post.createdAt}after the data has been parsed. ADateis an object, not text. - Rendering a response or error such as
{error}in a catch block. AnErrorobject is not a string. - Rendering a
Promise, which happens when anasynccall is placed straight in JSX without awaiting it.
How to tell if this is your problem
- Read the
found:part of the message. It names the shape.object with keys {id, name, email}is a record.[object Promise]is an unawaited call.[object Date]is a date. - Open the component in the stack trace and look for curly braces that hold a bare variable name rather than a property or a call.
- Log the value right above the return:
console.log(typeof value, value). Iftypeofsaysobject, that is the line.
The fix
Render a field, or convert the value to text on purpose:
// Before: the whole object
<p>{user}</p>
// After: the field you meant
<p>{user.name}</p>
// A date, converted explicitly
<p>{new Date(post.createdAt).toLocaleDateString()}</p>
// An error, as its message
<p>{error instanceof Error ? error.message : String(error)}</p>
If you do want a list, the error message tells you how: use an array, and give each item a key.
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
When the value is a promise, resolve it before rendering. In a client component, load it in an effect or a data library and render the result once it exists, with a loading state for the gap.
If you only need to see the data
For debugging, <pre>{JSON.stringify(value, null, 2)}</pre> prints any plain object safely. Remove it before you ship, since it can expose fields you did not mean to show.
How to avoid this next time
Add a rule to your agent’s instructions: “Never place an object, Date, Error or Promise directly in JSX. Render a specific field, format dates and errors to strings, and map arrays with a stable key.” In review, scan the curly braces in the returned markup: every one should hold text, a number, an element, or an array of those.
Comments
Sign in to join the conversation.
No comments yet — be the first.