facebook/flow · error · Error

updatePendingStatements: Variable for dependency

Error message

updatePendingStatements: Variable for dependency "${dep}" not found

What it means

During flowToFlowDef translation, every dependency name collected from a translated statement is looked up in context.variableMap, which createTranslationContext populated from module-scope variables only. If a dependency name has no entry, the name was never a module-scope variable (unresolved reference, global, or name from a non-module scope) and translation aborts with this error.

Solutions

  1. Add explicit imports or `declare var/function/type` statements for every referenced-but-undeclared identifier in the input file.
  2. Run the translator with recoverFromErrors: true so unsupported constructs degrade into error comments instead of aborting, then fix flagged inputs.
  3. Reduce the input to the failing declaration (the message names the dependency) and add the missing module-scope definition.
  4. If the dependency is a global, declare it: `declare var React: any;` at module level.

Example fix

// before
export const element = <div />; // React not imported

// after
import * as React from 'react';
export const element = <div />;
Defensive patterns

Strategy: try-catch

Validate before calling

// Check every referenced top-level identifier in input has a module-scope binding
import {analyze} from 'flow-eslint-scope'; // conceptually
function unboundModuleNames(ast, scopeManager) {
  const mod = scopeManager.globalScope.childScopes[0];
  const bound = new Set(mod.variables.map((v) => v.name));
  const unresolved = new Set();
  walk(ast, (n) => {
    if (n.type === 'Identifier' && !bound.has(n.name)) unresolved.add(n.name);
  });
  return [...unresolved];
}

Type guard

function isModuleScopeVariableName(context, name) {
  return context.variableMap.has(name);
}

Try / catch

try {
  const {code: out} = await translateFlowToFlowDef({code, recoverFromErrors: true});
} catch (e) {
  const m = /Variable for dependency "(.+)" not found/.exec(e.message);
  if (m) {
    report(`add an import or declare for "${m[1]}" in the input, then retry`);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling translateFlowToFlowDef on code whose exported/translated statements reference identifiers that are not declared or imported at module scope: bare globals used as types (e.g. JSX, React without import), references inside `declare module` bodies, or names that only exist in an outer/nested scope. recoverFromErrors does not cover this raw throw.

Common situations: Extracting libdefs from files that rely on ambient globals (React UMD global, JSX namespace) without imports; converting partial files that reference symbols defined in another file; incremental libdef extraction tooling hitting unimported references.

Related errors


AI-assisted analysis of facebook/flow@21c11b2ead (2026-08-20). Data as JSON: /api/errors/66448b9d11101f5a. Report an issue: GitHub.

Appendix: source

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

  function storeTranslatedStatement(
    stmt: DetachedNode<ProgramStatement>,
    orgStmt: ProgramStatement,
  ): void {
    translatedStatements.set(orgStmt, stmt);
  }

  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);
      }
    }
  }

View on GitHub (pinned to 21c11b2ead)