{"record":{"id":"e9ffe57b4eabdcd6","repo":"facebook/flow","slug":"import-export-cannot-be-replaced-into-a-replacem","errorCode":null,"errorMessage":"import/export cannot be replaced into a ${replacementParent.parent.type}.","messagePattern":"import/export cannot be replaced into a (.+?)\\.","errorType":"exception","errorClass":"InvalidReplacementError","httpStatus":null,"severity":"error","filePath":"packages/flow-transform/src/transform/mutations/ReplaceStatementWithMany.js","lineNumber":63,"sourceCode":"    nodesToReplaceWith,\n    keepComments: options?.keepComments ?? false,\n  };\n}\n\nexport function performReplaceStatementWithManyMutation(\n  mutationContext: MutationContext,\n  mutation: ReplaceStatementWithManyMutation,\n): ESNode {\n  const replacementParent = getStatementParent(mutation.target);\n\n  // enforce that if we are replacing with module declarations - they are being inserted in a valid location\n  if (\n    !isValidModuleDeclarationParent(\n      replacementParent.parent,\n      mutation.nodesToReplaceWith,\n    )\n  ) {\n    throw new InvalidReplacementError(\n      `import/export cannot be replaced into a ${replacementParent.parent.type}.`,\n    );\n  }\n\n  mutationContext.markDeletion(mutation.target);\n  mutationContext.markMutation(replacementParent.parent, replacementParent.key);\n\n  if (mutation.keepComments) {\n    // attach comments to the very first replacement node\n    moveCommentsToNewNode(mutation.target, mutation.nodesToReplaceWith[0]);\n  }\n\n  if (replacementParent.type === 'array') {\n    const parent: interface {\n      [string]: ReadonlyArray<DetachedNode<Statement | ModuleDeclaration>>,\n    } = replacementParent.parent;\n    parent[replacementParent.key] = astArrayMutationHelpers.replaceInArray(\n      parent[replacementParent.key],","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/facebook/flow/blob/d1341dac899a79c027762f6b423d896045287620/packages/flow-transform/src/transform/mutations/ReplaceStatementWithMany.js#L45-L81","documentation":"ReplaceStatementWithMany is the 'replace one statement with many nodes' mutation, and it runs the same module-declaration placement check as insertion: if any replacement node is an Import or Export declaration, the replaced statement's parent must be a Program (or a BlockStatement that is a DeclareModule body). Otherwise it throws InvalidReplacementError naming the offending parent type, because an import or export inside a nested block is not legal JavaScript.","triggerScenarios":"replaceWithMany(target, [importDecl, ...rest]) where target is a statement nested in a function body, if-block, or SwitchCase: getStatementParent(target).parent.type is anything but Program or a DeclareModule's BlockStatement.","commonSituations":"Codemods that rewrite a statement into an 'import + call + export' bundle and fire on nested statements; export-generation transforms anchored on the last statement of a function instead of the module.","solutions":["Split the mutation: put module declarations in a separate replace or insert anchored at a top-level statement","Walk up from the target to the first statement whose parent is Program and chain the mutations there","Drop the import and export nodes from the replacement batch if the nested location must be kept"],"exampleFix":"// before\nmutations.push(replaceWithMany(nestedStmt, [importDecl, callStmt])); // throws\n\n// after\nmutations.push(replaceWithMany(nestedStmt, [callStmt]));\nlet top = nestedStmt;\nwhile (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 canReplaceHere(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(replaceWithMany(target, nodes));\n} catch (e) {\n  if (e.message.includes('import/export cannot be replaced')) {\n    // split: local statements replace in place, module declarations hoist to top level\n    mutations.push(replaceWithMany(target, nodes.filter(n => !isModuleDeclaration(n))));\n    mutations.push(insertStatement('before', topLevelOf(target), nodes.filter(isModuleDeclaration)));\n  } else throw e;\n}","preventionTips":["Only include import and export nodes in replaceWithMany batches anchored at top-level statements","Check target.parent.type === 'Program' before issuing module-declaration replacements","Split mixed batches: local statements replace in place, module declarations hoist to Program.body"],"tags":["flow-transform","replacement","import","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"}