{"record":{"id":"f9257342882a0f58","repo":"facebook/flow","slug":"import-export-cannot-be-inserted-into-a-insertio","errorCode":null,"errorMessage":"import/export cannot be inserted into a ${insertionParent.parent.type}.","messagePattern":"import/export cannot be inserted into a (.+?)\\.","errorType":"exception","errorClass":"InvalidInsertionError","httpStatus":null,"severity":"error","filePath":"packages/flow-transform/src/transform/mutations/InsertStatement.js","lineNumber":63,"sourceCode":"export function performInsertStatementMutation(\n  mutationContext: MutationContext,\n  mutation: InsertStatementMutation,\n): ESNode {\n  mutationContext.assertNotDeleted(\n    mutation.target,\n    `Attempted to insert ${mutation.side} a deleted ${mutation.target.type} node. This likely means that you attempted to mutate around the target after it was deleted/replaced.`,\n  );\n\n  const insertionParent = getStatementParent(mutation.target);\n\n  // enforce that if we are inserting module declarations - they are being inserted in a valid location\n  if (\n    !isValidModuleDeclarationParent(\n      insertionParent.parent,\n      mutation.nodesToInsert,\n    )\n  ) {\n    throw new InvalidInsertionError(\n      `import/export cannot be inserted into a ${insertionParent.parent.type}.`,\n    );\n  }\n\n  mutationContext.markMutation(insertionParent.parent, insertionParent.key);\n\n  if (insertionParent.type === 'array') {\n    const parent: interface {\n      [string]: ReadonlyArray<DetachedNode<Statement | ModuleDeclaration>>,\n    } = insertionParent.parent;\n    switch (mutation.side) {\n      case 'before': {\n        parent[insertionParent.key] = astArrayMutationHelpers.insertInArray(\n          parent[insertionParent.key],\n          insertionParent.targetIndex,\n          mutation.nodesToInsert,\n        );\n        break;","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/facebook/flow/blob/d1341dac899a79c027762f6b423d896045287620/packages/flow-transform/src/transform/mutations/InsertStatement.js#L45-L81","documentation":"InsertStatement validates insertion sites for module declarations: imports and exports are only legal as direct children of a Program (top level) or of a BlockStatement that is the body of a Flow DeclareModule. isValidModuleDeclarationParent returns false when any node being inserted is an Import or Export declaration and the insertion parent is anything else, and this InvalidInsertionError is the result.","triggerScenarios":"insertStatementMutation('before' or 'after', target, nodes) where any node in nodes is an ImportDeclaration or Export* and the target's statement parent is a BlockStatement (function or if body), SwitchCase, or another non-Program container.","commonSituations":"Auto-import codemods (e.g. adding an import for an undefined identifier) anchoring on the first statement that references the identifier, which sits inside a function; inserting an export statement inside a nested block.","solutions":["Anchor the insertion on a top-level statement: walk up from the target until parent.type === 'Program'","For DeclareModule bodies, ensure the anchor's parent is the DeclareModule's BlockStatement","If you only need non-module statements inserted, the nested location is fine: drop the import from the batch"],"exampleFix":"// before\nconst target = referencingStmt; // nested in a function body\nmutations.push(insertStatement('before', target, [importDecl])); // throws\n\n// after\nlet top = target;\nwhile (top.parent && top.parent.type !== 'Program') top = top.parent;\nmutations.push(insertStatement('before', top, [importDecl]));","handlingStrategy":"validation","validationCode":"const MODULE_DECLS = new Set(['ImportDeclaration', 'ExportNamedDeclaration', 'ExportDefaultDeclaration', 'ExportAllDeclaration']);\nfunction canInsertHere(target, nodes) {\n  const p = target.parent;\n  const parentOk = p.type === 'Program' ||\n    (p.type === 'BlockStatement' && p.parent && p.parent.type === 'DeclareModule');\n  const hasModuleDecl = nodes.some(n => MODULE_DECLS.has(n.type));\n  return !hasModuleDecl || parentOk;\n}","typeGuard":"const isModuleDeclaration = (n) =>\n  n.type === 'ImportDeclaration' || n.type === 'ExportNamedDeclaration' ||\n  n.type === 'ExportDefaultDeclaration' || n.type === 'ExportAllDeclaration';","tryCatchPattern":"try {\n  mutations.push(insertStatement(side, target, nodes));\n} catch (e) {\n  if (e.message.includes('import/export cannot be inserted')) {\n    // hoist anchor to top level and retry\n    let top = target;\n    while (top.parent && top.parent.type !== 'Program') top = top.parent;\n    mutations.push(insertStatement('before', top, nodes));\n  } else throw e;\n}","preventionTips":["Anchor import and export insertions on statements whose parent is Program","Check target.parent.type before issuing insertStatement for module declarations","In generated codemods, always hoist to the module top level instead of using the reference site"],"tags":["flow-transform","import","insertion","module-scope"],"backgroundTag":"invalid-import-insertion-location","analyzedSha":"d1341dac899a79c027762f6b423d896045287620","analyzedAt":"2026-08-17T00:07:02.212Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}