{"id":"6de874de56fc72c7","repo":"babel/babel","slug":"file-program-node-we-can-t-possibly-find-a-statem","errorCode":null,"errorMessage":"File/Program node, we can't possibly find a statement parent to this","messagePattern":"File/Program node, we can't possibly find a statement parent to this","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/babel-traverse/src/path/ancestry.ts","lineNumber":73,"sourceCode":"\nexport function getStatementParent(\n  this: NodePath<t.Node | null>,\n): NodePath<t.Statement> {\n  let path = this;\n\n  do {\n    if (\n      !path.parentPath ||\n      (Array.isArray(path.container) && path.isStatement())\n    ) {\n      break;\n    } else {\n      path = path.parentPath;\n    }\n  } while (path);\n\n  if (path && (path.isProgram() || path.isFile())) {\n    throw new Error(\n      \"File/Program node, we can't possibly find a statement parent to this\",\n    );\n  }\n\n  return path as NodePath<t.Statement>;\n}\n\n/**\n * Get the deepest common ancestor and then from it, get the earliest relationship path\n * to that ancestor.\n *\n * Earliest is defined as being \"before\" all the other nodes in terms of list container\n * position and visiting key.\n */\n\nexport function getEarliestCommonAncestorFrom(\n  this: NodePath,\n  paths: NodePath[],","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/babel/babel/blob/06b6eae39da4ce0689fad64e2c48a6375a464208/packages/babel-traverse/src/path/ancestry.ts#L55-L91","documentation":"getStatementParent() walks up the ancestry to find the nearest path whose container is a statement array (the body of a Program/Block/Loop/etc.). If the walk terminates at a Program or File node without ever finding such a container, there is no enclosing statement list, so it throws rather than return a misleading path.","triggerScenarios":"Calling path.getStatementParent() on a node that is already at the top level (e.g., the Program node itself, or a directive directly under Program); calling it on a node whose only ancestors are Program/File.","commonSituations":"A visitor that inserts statements via getStatementParent but is invoked on the Program or a top-level directive; plugins that assume the current path is always nested inside a function/block.","solutions":["Guard the call: if (path.parentPath && !path.isProgram() && !path.isFile()) path.getStatementParent().","Insert relative to a known container instead, e.g. path.parentPath.isProgram() ? path : path.getStatementParent().","Restructure so the visitor runs on a path that is guaranteed inside a block/function body."],"exampleFix":"// before\nProgram(path) {\n  path.getStatementParent(); // throws: already Program\n}\n\n// after\nProgram(path) {\n  path.pushContainer('body', myStatement()); // insert directly into program body\n}","handlingStrategy":"type-guard","validationCode":"function safeGetStatementParent(path) {\n  if (!path.parentPath || path.isProgram() || path.isFile()) {\n    return null; // no enclosing statement list\n  }\n  return path.getStatementParent();\n}","typeGuard":"function hasStatementAncestor(path) {\n  return !!path.findParent(p => Array.isArray(p.container) && p.isStatement());\n}","tryCatchPattern":null,"preventionTips":["Guard getStatementParent() calls with isProgram()/isFile() checks.","Prefer pushContainer on a known body key instead of getStatementParent when possible.","Restrict visitors that use getStatementParent to non-root node types."],"tags":["babel-traverse","ancestry","statement-parent","path"],"analyzedSha":"06b6eae39da4ce0689fad64e2c48a6375a464208","analyzedAt":"2026-08-03T20:13:43.465Z","schemaVersion":2}