{"record":{"id":"3355006d2f2694b4","repo":"facebook/flow","slug":"updatependingstatements-variable-parent-of-dep","errorCode":null,"errorMessage":"updatePendingStatements: Variable parent of \"${dep}\" not found","messagePattern":"updatePendingStatements: Variable parent of \"(.+?)\" not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/flow-api-translator/src/flowToFlowDef.js","lineNumber":198,"sourceCode":"  const seenDeps = new Set<Dep>();\n  const processedStatements = new Set<ProgramStatement>();\n  const pendingStatements = new Set<ProgramStatement>();\n  function updatePendingStatements(deps: TranslatedDeps): void {\n    for (const dep of deps) {\n      if (seenDeps.has(dep)) {\n        continue;\n      }\n      seenDeps.add(dep);\n      const variable = context.variableMap.get(dep);\n      if (variable == null) {\n        throw new Error(\n          `updatePendingStatements: Variable for dependency \"${dep}\" not found`,\n        );\n      }\n      for (const def of variable.defs) {\n        const stmt = def.node;\n        if (stmt == null) {\n          throw new Error(\n            `updatePendingStatements: Variable parent of \"${dep}\" not found`,\n          );\n        }\n        const topLevelStmt = getTopLevelStatement(stmt, context);\n        if (processedStatements.has(topLevelStmt)) {\n          continue;\n        }\n        pendingStatements.add(topLevelStmt);\n      }\n    }\n  }\n  function updateProcessedStatement(stmt: ProgramStatement): void {\n    processedStatements.add(stmt);\n    pendingStatements.delete(stmt);\n  }\n\n  // Process all export statements\n  for (const stmt of ast.body) {","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/facebook/flow/blob/d1341dac899a79c027762f6b423d896045287620/packages/flow-api-translator/src/flowToFlowDef.js#L180-L216","documentation":"Companion invariant in flowToFlowDef: the dependency name was found in context.variableMap, but one of its VariableDefinition entries has a null node, so the translator cannot find the statement that defines the dependency and throws, naming the dependency.","triggerScenarios":"The variableMap contains a Variable whose defs array includes a definition with no attached AST node — typically an AST that was rebuilt or cloned without parent/def links, or a definition node detached during earlier processing.","commonSituations":"Programmatic AST manipulation (recast/babel/ts-morph style transforms) that drops parent links; a defs array built by a different package version than the one consuming it; hand-constructed scope data.","solutions":["Re-translate from the original, unmodified parse output instead of a transformed/cloned AST","Keep the parser package and flow-api-translator at matching versions","Minimize the input and file an issue — a null def node is a translator-internal bug"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// If you build the variableMap yourself, assert every def carries its node:\nfunction defsAreComplete(variableMap: Map<string, {defs: Array<{node: unknown}>}>): boolean {\n  for (const v of variableMap.values()) {\n    for (const def of v.defs) {\n      if (def.node == null) return false;\n    }\n  }\n  return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n  translateFlowASTToFlowDef(program, context);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Variable parent of')) {\n    // rebuild the AST from a fresh parse and retry once; otherwise report\n  } else throw err;\n}","preventionTips":["Never feed cloned/rebuilt ASTs that dropped parent or def links","Parse and translate with matching package versions","Keep the original parse output untouched until translation finishes"],"tags":["flow","ast","transformation","internal-invariant","scope"],"backgroundTag":"invalid-ast-structure","analyzedSha":"d1341dac899a79c027762f6b423d896045287620","analyzedAt":"2026-08-17T00:07:02.212Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}