facebook/flow · error · Error

updatePendingStatements: Variable parent of "${dep}" not fou

Error message

updatePendingStatements: Variable parent of "${dep}" not found

What it means

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.

Source

Thrown at packages/flow-api-translator/src/flowToFlowDef.js:198

  const seenDeps = new Set<Dep>();
  const processedStatements = new Set<ProgramStatement>();
  const pendingStatements = new Set<ProgramStatement>();
  function updatePendingStatements(deps: TranslatedDeps): void {
    for (const dep of deps) {
      if (seenDeps.has(dep)) {
        continue;
      }
      seenDeps.add(dep);
      const variable = context.variableMap.get(dep);
      if (variable == null) {
        throw new Error(
          `updatePendingStatements: Variable for dependency "${dep}" not found`,
        );
      }
      for (const def of variable.defs) {
        const stmt = def.node;
        if (stmt == null) {
          throw new Error(
            `updatePendingStatements: Variable parent of "${dep}" not found`,
          );
        }
        const topLevelStmt = getTopLevelStatement(stmt, context);
        if (processedStatements.has(topLevelStmt)) {
          continue;
        }
        pendingStatements.add(topLevelStmt);
      }
    }
  }
  function updateProcessedStatement(stmt: ProgramStatement): void {
    processedStatements.add(stmt);
    pendingStatements.delete(stmt);
  }

  // Process all export statements
  for (const stmt of ast.body) {

View on GitHub (pinned to d1341dac89)

Solutions

  1. Re-translate from the original, unmodified parse output instead of a transformed/cloned AST
  2. Keep the parser package and flow-api-translator at matching versions
  3. Minimize the input and file an issue — a null def node is a translator-internal bug
Defensive patterns

Strategy: validation

Validate before calling

// If you build the variableMap yourself, assert every def carries its node:
function defsAreComplete(variableMap: Map<string, {defs: Array<{node: unknown}>}>): boolean {
  for (const v of variableMap.values()) {
    for (const def of v.defs) {
      if (def.node == null) return false;
    }
  }
  return true;
}

Try / catch

try {
  translateFlowASTToFlowDef(program, context);
} catch (err) {
  if (err instanceof Error && err.message.includes('Variable parent of')) {
    // rebuild the AST from a fresh parse and retry once; otherwise report
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of facebook/flow@d1341dac89 (2026-08-17). Data as JSON: /api/errors/3355006d2f2694b4. Report an issue: GitHub.