facebook/flow · error · InvalidStatementError
Expected to find a valid statement parent, but found a…
Error message
Expected to find a valid statement parent, but found a parent of type "${parent.type}". What it means
InvalidStatementError thrown at the end of getStatementParent's switch: statement mutations only support anchors whose parent is one of IfStatement, LabeledStatement, WithStatement, DoWhileStatement, WhileStatement, ForStatement, ForInStatement, ForOfStatement, SwitchCase, BlockStatement, or Program. Any other parent type (e.g. ExportDefaultDeclaration, ClassBody, or an expression parent) falls through to this throw.
Solutions
- Ensure the anchor is a direct Statement/ModuleDeclaration child of one of the supported parent types.
- For expression-level changes, use replaceNode/replaceNodeWithContext instead of statement mutations.
- If a legitimate statement location is unsupported, upstream a case to getStatementParent.
Example fix
// before mutate.insertStatementBefore(expressionNode, stmt); // parent not a statement container - throws // after mutate.insertStatementBefore(enclosingStatement, stmt);
Defensive patterns
Strategy: type-guard
Validate before calling
const STATEMENT_PARENTS = new Set([
'IfStatement', 'LabeledStatement', 'WithStatement', 'DoWhileStatement',
'WhileStatement', 'ForStatement', 'ForInStatement', 'ForOfStatement',
'SwitchCase', 'BlockStatement', 'Program',
]);
if (STATEMENT_PARENTS.has(anchor.parent.type)) {
mutate.insertStatementBefore(anchor, stmt);
} Type guard
function hasSupportedStatementParent(anchor): boolean {
return [
'IfStatement', 'LabeledStatement', 'WithStatement', 'DoWhileStatement',
'WhileStatement', 'ForStatement', 'ForInStatement', 'ForOfStatement',
'SwitchCase', 'BlockStatement', 'Program',
].includes(anchor.parent.type);
} Prevention
- Verify the anchor's parent type is in the supported switch before mutating.
- For unsupported parents, fall back to replaceNode on the enclosing expression.
When it happens
Trigger: Calling insertStatement*/statement removal with an anchor whose parent type is not in the supported list - commonly an expression node whose parent is a CallExpression/VariableDeclarator, or a declaration nested somewhere the switch does not model.
Common situations: Passing a non-Statement node as the anchor (same root cause as the `test`/`init` assertion but hitting the fall-through instead); new or unusual AST shapes not covered by the supported-parent switch.
Related errors
- Attempted to insert a statement into
- Could not find target in array of
- Expected to find the target
- Cannot perform a remove mutation on node of type
- Could not find target in array of
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/fc349cdc2bab3752.
Report an issue: GitHub.
Appendix: source
Thrown at packages/flow-transform/src/transform/mutations/utils/getStatementParent.js:130
type: 'array',
parent,
key: 'consequent',
targetIndex: getAssertedIndex('consequent', parent.consequent),
};
}
case 'BlockStatement':
case 'Program': {
return {
type: 'array',
parent,
key: 'body',
targetIndex: getAssertedIndex('body', parent.body),
};
}
}
throw new InvalidStatementError(
`Expected to find a valid statement parent, but found a parent of type "${parent.type}".`,
);
})();
if (
// array insertions are already validated by the getAssertedIndex function
result.targetIndex == null &&
// $FlowExpectedError[prop-missing]
// $FlowFixMe[invalid-compare]
result.parent[result.key] !== target
) {
throw new InvalidStatementError(
`Expected to find the target "${target.type}" on the "${result.parent.type}.${result.key}", but found a different node. ` +
'This likely means that you attempted to mutate around the target after it was deleted/replaced.',
);
}
return result;View on GitHub (pinned to f88ac94bcf)