facebook/react · warning · Error
489
489
Error message
Expected the resume to render <${node[0]}> in this slot but instead it rendered <${name}>. The tree doesn't match so React will fallback to client rendering. What it means
During resume, a slot recorded at prerender time expected a component named X (stored as node[0]), but the resumed render produced a component with a different name at the same key/index. As a precaution React verifies the name matches; on mismatch it throws error code 489 and the boundary falls back to client rendering.
Source
Thrown at packages/react-server/src/ReactFizzServer.js:3256
childIndex: number,
type: any,
props: Object,
ref: any,
replay: ReplaySet,
): void {
// We're replaying. Find the path to follow.
const replayNodes = replay.nodes;
for (let i = 0; i < replayNodes.length; i++) {
// Flow doesn't support refinement on tuples so we do it manually here.
const node = replayNodes[i];
if (keyOrIndex !== node[1]) {
continue;
}
if (node.length === 4) {
// Matched a replayable path.
// Let's double check that the component name matches as a precaution.
if (name !== null && name !== node[0]) {
throw new Error(
'Expected the resume to render <' +
(node[0] as any) +
'> in this slot but instead it rendered <' +
name +
'>. ' +
"The tree doesn't match so React will fallback to client rendering.",
);
}
const childNodes = node[2];
const childSlots = node[3];
const currentNode = task.node;
task.replay = {nodes: childNodes, slots: childSlots, pendingTasks: 1};
try {
renderElement(request, task, keyPath, type, props, ref);
if (
task.replay.pendingTasks === 1 &&
task.replay.nodes.length > 0
// TODO check remaining slotsView on GitHub (pinned to eafeac097b)
Solutions
- Render the same component at each slot in both passes (pin code versions between prerender and resume)
- Keep the component at the slot stable and vary only its props instead of its identity
- Move flag-dependent component choices behind a postponed or client-rendered boundary
- Regenerate the prerendered payload after renaming or swapping components
Example fix
// before
// prerender: <OldButton>; resume (flag flipped): <NewButton> in the same slot -> throws
return flag ? <NewButton /> : <OldButton />;
// after
// keep one stable component at the slot and vary props
return <Button variant={flag ? 'new' : 'old'} />; Defensive patterns
Strategy: fallback
Try / catch
// React catches this and client-renders the boundary; no user try/catch needed.
// Log via the render/resume error hooks:
// onError(err) { log.warn('slot component mismatch -> client fallback:', err.message); } Prevention
- Keep the component identity at each resumed slot stable across passes
- Vary props, not component identity, when behavior must differ
- Regenerate prerendered payloads whenever components are renamed or swapped
When it happens
Trigger: The component at a given position changed identity between prerender and resume: a renamed component, a dynamic import resolving to a different implementation, an A/B flag flipping the branch, or a different dependency version in the resume environment.
Common situations: Deploying renamed components while resuming old prerendered payloads; per-request feature flags choosing different components; vendored vs npm versions of a component resolving differently.
Related errors
- 488
- 490
- File/Blob fields are not yet supported in progressive forms.
- Can only set one of `children` or `props.dangerouslySetInner
- `props.dangerouslySetInnerHTML` must be in the form `{__html
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/52bb59aa82691e3b.
Report an issue: GitHub.