facebook/flow · error
Cannot insert array into non-array parent type
Error message
Cannot insert array into non-array parent type: ${parent.type} What it means
replaceNodeOnParent accepts either a single node or an array of nodes, but an array is only valid when the located parent slot is itself an array property (replacementParent.type === 'array'). Replacing a single-node slot (e.g. `argument`, `body`, `init`) with multiple nodes has no valid representation, so it throws naming the parent type.
Solutions
- Insert multiple nodes into an array slot instead: find the enclosing array (e.g. program/body or block.body) and use the array-based mutation path with the correct index.
- If you must keep the slot, wrap the multiple nodes in a single container node (e.g. a SequenceExpression or a Block) as appropriate for the grammar.
- Pass a single node when the target slot is single-valued.
Example fix
// before replaceNodeOnParent(stmt, [decl, call]); // stmt sits in body[i] via single key -> throws // after const body = program.body; const idx = body.indexOf(stmt); replaceInArray(body, idx, [decl, call]); // array slot supports multiple nodes
Defensive patterns
Strategy: validation
Validate before calling
// Verify the target slot is an array before replacing with many nodes
function canReplaceWithMany(target) {
const parent = target.parent;
return Object.keys(parent).some((k) => Array.isArray(parent[k]) && parent[k].includes(target));
} Type guard
function isInArraySlot(target) {
const parent = target.parent;
if (parent == null) return false;
return Object.keys(parent).some((k) => Array.isArray(parent[k]) && parent[k].includes(target));
} Prevention
- Only pass arrays to replaceNodeOnParent when the node lives in an array property (body, params, arguments).
- For single-node slots, replace with one node or restructure the enclosing array.
When it happens
Trigger: Calling replaceNodeOnParent(node, [a, b]) where node sits in a single-node position such as an expression's argument, a declaration's init, or a function's id — anywhere the visitor key holds one node rather than an array.
Common situations: Codemods that expand one statement/expression into several (e.g. splitting an expression into multiple statements) without moving to a statement-list slot; generic 'replace with list' helpers applied to arbitrary nodes.
Related errors
- Expected parent node to be set on
- Invalid Mutation: Tried to mutate an elements array with an…
- No visitor keys found for node type
- SimpleTransform: invalid array result for root node
- SimpleTransform.transformProgram: Expected program node.
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/7c798af046e16c52.
Report an issue: GitHub.
Appendix: source
Thrown at packages/flow-parser/oxidized-src/transform/astNodeMutationHelpers.js:105
const replacementParent = getParentKey(
originalNode,
originalNodeParent,
visitorKeys,
);
const parent = replacementParent.node;
if (replacementParent.type === 'array') {
// $FlowExpectedError[prop-missing]
parent[replacementParent.key] = replaceInArray(
// $FlowExpectedError[prop-missing]
parent[replacementParent.key],
replacementParent.targetIndex,
Array.isArray(nodeToReplaceWith)
? nodeToReplaceWith
: [nodeToReplaceWith],
);
} else {
if (Array.isArray(nodeToReplaceWith)) {
throw new Error(
`Cannot insert array into non-array parent type: ${parent.type}`,
);
}
// $FlowExpectedError[prop-missing]
parent[replacementParent.key] = nodeToReplaceWith;
}
}
/**
* Remove a node from the AST its connected to (via the parent pointer).
*/
export function removeNodeOnParent(
originalNode: ESNode,
originalNodeParent: ESNode,
visitorKeys?: ?VisitorKeysType,
): void {
const replacementParent = getParentKey(
originalNode,View on GitHub (pinned to f88ac94bcf)