{"record":{"id":"fc349cdc2bab3752","repo":"facebook/flow","slug":"expected-to-find-a-valid-statement-parent-but-fou","errorCode":null,"errorMessage":"Expected to find a valid statement parent, but found a parent of type \"${parent.type}\".","messagePattern":"Expected to find a valid statement parent, but found a parent of type \"(.+?)\"\\.","errorType":"exception","errorClass":"InvalidStatementError","httpStatus":null,"severity":"error","filePath":"packages/flow-transform/src/transform/mutations/utils/getStatementParent.js","lineNumber":130,"sourceCode":"          type: 'array',\n          parent,\n          key: 'consequent',\n          targetIndex: getAssertedIndex('consequent', parent.consequent),\n        };\n      }\n\n      case 'BlockStatement':\n      case 'Program': {\n        return {\n          type: 'array',\n          parent,\n          key: 'body',\n          targetIndex: getAssertedIndex('body', parent.body),\n        };\n      }\n    }\n\n    throw new InvalidStatementError(\n      `Expected to find a valid statement parent, but found a parent of type \"${parent.type}\".`,\n    );\n  })();\n\n  if (\n    // array insertions are already validated by the getAssertedIndex function\n    result.targetIndex == null &&\n    // $FlowExpectedError[prop-missing]\n    // $FlowFixMe[invalid-compare]\n    result.parent[result.key] !== target\n  ) {\n    throw new InvalidStatementError(\n      `Expected to find the target \"${target.type}\" on the \"${result.parent.type}.${result.key}\", but found a different node. ` +\n        'This likely means that you attempted to mutate around the target after it was deleted/replaced.',\n    );\n  }\n\n  return result;","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/packages/flow-transform/src/transform/mutations/utils/getStatementParent.js#L112-L148","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmutate.insertStatementBefore(expressionNode, stmt); // parent not a statement container - throws\n\n// after\nmutate.insertStatementBefore(enclosingStatement, stmt);","handlingStrategy":"type-guard","validationCode":"const STATEMENT_PARENTS = new Set([\n  'IfStatement', 'LabeledStatement', 'WithStatement', 'DoWhileStatement',\n  'WhileStatement', 'ForStatement', 'ForInStatement', 'ForOfStatement',\n  'SwitchCase', 'BlockStatement', 'Program',\n]);\n\nif (STATEMENT_PARENTS.has(anchor.parent.type)) {\n  mutate.insertStatementBefore(anchor, stmt);\n}","typeGuard":"function hasSupportedStatementParent(anchor): boolean {\n  return [\n    'IfStatement', 'LabeledStatement', 'WithStatement', 'DoWhileStatement',\n    'WhileStatement', 'ForStatement', 'ForInStatement', 'ForOfStatement',\n    'SwitchCase', 'BlockStatement', 'Program',\n  ].includes(anchor.parent.type);\n}","tryCatchPattern":null,"preventionTips":["Verify the anchor's parent type is in the supported switch before mutating.","For unsupported parents, fall back to replaceNode on the enclosing expression."],"tags":["flow","flow-transform","codemod","statement-anchor","ast-mutation"],"backgroundTag":"invalid-ast-mutation","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","contentChangedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}