facebook/flow · error · Error

ImportDeclaration should appear when the mode is ES6 and in

Error message

ImportDeclaration should appear when the mode is ES6 and in the module context.

What it means

In flow-eslint's scope Referencer (an eslint-scope port), visiting an ImportDeclaration requires the scope manager to have been created with ecmaVersion >= 6 (isES6) and sourceType 'module' (isModule). If the analyzed source contains an import statement but analysis was not configured for ES modules, this invariant throws.

Source

Thrown at packages/flow-eslint/src/scope-manager/referencer/Referencer.js:668

    this.visitFunction(node);
  }

  FunctionExpression(node: FunctionExpression): void {
    this.visitFunction(node);
  }

  Identifier(node: Identifier): void {
    this.currentScope().referenceValue(node);
    this.visitType(node.typeAnnotation);
  }

  ImportAttribute(_: ImportAttribute): void {
    // import assertions are module metadata and thus have no variables to reference
  }

  ImportDeclaration(node: ImportDeclaration): void {
    if (!this.scopeManager.isES6() || !this.scopeManager.isModule()) {
      throw new Error(
        'ImportDeclaration should appear when the mode is ES6 and in the module context.',
      );
    }

    ImportVisitor.visit(this, node);
  }

  JSXAttribute(node: JSXAttribute): void {
    this.visit(node.value);
  }

  JSXClosingElement(node: JSXClosingElement): void {
    /**
     * Note that this was not previously considered to be a reference and that
     * other scope analyzers do not count them either: e.g. TypeScript-eslint
     * https://fburl.com/4q93a3x3
     *
     * We are considering this a reference because it technically includes an

View on GitHub (pinned to d1341dac89)

Solutions

  1. Set `parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }` in your eslint/analysis config
  2. If the file really is a CommonJS script, remove the import statements rather than changing the config
  3. When constructing the scope analysis programmatically, pass the same ecmaVersion/sourceType you passed the parser

Example fix

// before (.eslintrc.js)
module.exports = { rules: { /* ... */ } };

// after (.eslintrc.js)
module.exports = {
  parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
  rules: { /* ... */ },
};
Defensive patterns

Strategy: validation

Validate before calling

function isEsmAnalysisConfig(parserOptions: {
  ecmaVersion?: number | 'latest';
  sourceType?: string;
}): boolean {
  const ecma = parserOptions?.ecmaVersion ?? 5;
  const ecmaNum = ecma === 'latest' ? 2022 : Number(ecma);
  return parserOptions?.sourceType === 'module' && ecmaNum >= 2015;
}

Type guard

function canAnalyzeImports(opts: {ecmaVersion?: unknown; sourceType?: unknown}): boolean {
  const ecma = opts.ecmaVersion == null ? 5 : opts.ecmaVersion === 'latest' ? 2022 : Number(opts.ecmaVersion);
  return opts.sourceType === 'module' && ecma >= 2015;
}

Prevention

When it happens

Trigger: Running flow-eslint or equivalent scope analysis with parserOptions missing `sourceType: 'module'` (default is 'script') or with ecmaVersion below 2015, while the analyzed code contains import/export statements.

Common situations: Missing or partial parserOptions in .eslintrc; lint setups switched to ESM files without config updates; embedding the Referencer in custom tooling and forgetting to pass the parser's options to the scope manager.

Related errors


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