facebook/react · warning
copyWithRename() expects paths of the same length
Error message
copyWithRename() expects paths of the same length
What it means
copyWithRename is the immutable clone helper behind the DevTools override APIs overrideHookStateRenamePath (ReactFiberReconciler.js:766) and overridePropsRenamePath (ReactFiberReconciler.js:813). It validates that oldPath and newPath have identical length, because it only renames the deepest key of a fixed path. On mismatch it warns and returns undefined - which the caller then assigns to hook.memoizedState/baseState or fiber.pendingProps, silently wiping that state or props to undefined.
Source
Thrown at packages/react-reconciler/src/ReactFiberReconciler.js:666
// $FlowFixMe[incompatible-use] number or string is fine here
updated[oldKey] = copyWithRenameImpl(
// $FlowFixMe[incompatible-use] number or string is fine here
obj[oldKey],
oldPath,
newPath,
index + 1,
);
}
return updated;
};
const copyWithRename = (
obj: Object | Array<any>,
oldPath: Array<string | number>,
newPath: Array<string | number>,
): Object | Array<any> => {
if (oldPath.length !== newPath.length) {
console.warn('copyWithRename() expects paths of the same length');
return;
} else {
for (let i = 0; i < newPath.length - 1; i++) {
if (oldPath[i] !== newPath[i]) {
console.warn(
'copyWithRename() expects paths to be the same except for the deepest key',
);
return;
}
}
}
return copyWithRenameImpl(obj, oldPath, newPath, 0);
};
const copyWithSetImpl = (
obj: Object | Array<any>,
path: Array<string | number>,
index: number,View on GitHub (pinned to eafeac097b)
Solutions
- Pass paths of the same length: rename only the deepest key, e.g. ['user','name'] to ['user','username']
- Fix the tool's path builder so both arrays come from the same selected node
- For a move between depths, use delete then set (overrideHookStateDeletePath followed by overrideHookState) instead of rename
Example fix
// before: lengths differ (1 vs 2) - warns, state becomes undefined overridePropsRenamePath(fiber, ['user'], ['profile', 'name']); // after: same depth, only deepest key renamed overridePropsRenamePath(fiber, ['user', 'name'], ['user', 'username']);
Defensive patterns
Strategy: type-guard
Validate before calling
// validate before calling the DevTools override
if (!isValidRenamePath(oldPath, newPath)) {
throw new Error('rename requires equal-length paths');
}
overrideHookStateRenamePath(fiber, id, oldPath, newPath); Type guard
function isValidRenamePath(oldPath, newPath) {
return (
Array.isArray(oldPath) &&
Array.isArray(newPath) &&
oldPath.length === newPath.length &&
oldPath.length > 0 &&
oldPath.every((key, i) => i === oldPath.length - 1 || key === newPath[i])
);
} Prevention
- Build oldPath and newPath from the same selected tree node
- Remember copyWithRename only renames the deepest key - use delete+set for structural moves
- Cover rename paths with unit tests when writing DevTools-like tooling
When it happens
Trigger: Calling overrideHookStateRenamePath(fiber, id, ['user'], ['profile','name']) or overridePropsRenamePath(fiber, ['a'], ['a','b']) - any rename where the two path arrays differ in length. Only reachable from DevTools-style tooling or tests that drive the DevTools hook, never from normal rendering.
Common situations: Custom DevTools forks or inspector UIs that build the two path arrays from different tree states (one captured before expanding a node, one after); test harnesses simulating inline state editing; tools that allow renaming a key while also moving it between depths.
Related errors
- copyWithRename() expects paths to be the same except for the
- An unsupported type was passed to use(): ${String(usable)}
- Unknown Fiber. Needs to be a function component to inspect h
- Hooks not supported by this renderer
- getProfilingData not supported by this renderer
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/8c3a2c026f4ebb6b.
Report an issue: GitHub.