facebook/react · error · Error

Unable to acquire scope for the current node. This is a bug

Error message

Unable to acquire scope for the current node. This is a bug in eslint-plugin-react-hooks, please file an issue.

What it means

The react-hooks/exhaustive-deps rule analyzes each hook callback by asking ESLint's ScopeManager for the variable scope of the callback node (scopeManager.acquire(node)). If the scope manager returns null for a node that must have a scope, the rule cannot compute dependencies and aborts with this invariant error. The message itself states it is a bug in eslint-plugin-react-hooks, not a problem in your code. It almost always indicates a mismatch between the AST a parser produced and what the scope manager can map.

Source

Thrown at packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts:210

          message:
            `Effect callbacks are synchronous to prevent race conditions. ` +
            `Put the async function inside:\n\n` +
            'useEffect(() => {\n' +
            '  async function fetchData() {\n' +
            '    // You can await here\n' +
            '    const response = await MyAPI.getData(someId);\n' +
            '    // ...\n' +
            '  }\n' +
            '  fetchData();\n' +
            `}, [someId]); // Or [] if effect doesn't need props or state\n\n` +
            'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching',
        });
      }

      // Get the current scope.
      const scope = scopeManager.acquire(node);
      if (!scope) {
        throw new Error(
          'Unable to acquire scope for the current node. This is a bug in eslint-plugin-react-hooks, please file an issue.',
        );
      }

      // Find all our "pure scopes". On every re-render of a component these
      // pure scopes may have changes to the variables declared within. So all
      // variables used in our reactive hook callback but declared in a pure
      // scope need to be listed as dependencies of our reactive hook callback.
      //
      // According to the rules of React you can't read a mutable value in pure
      // scope. We can't enforce this in a lint so we trust that all variables
      // declared outside of pure scope are indeed frozen.
      const pureScopes = new Set();
      let componentScope: Scope.Scope | null = null;
      {
        let currentScope = scope.upper;
        while (currentScope) {
          pureScopes.add(currentScope);

View on GitHub (pinned to eafeac097b)

Solutions

  1. Update eslint-plugin-react-hooks to the latest version - several scope-acquisition crashes have been fixed across releases
  2. Align parser tooling: bump or pin @typescript-eslint/parser and eslint to versions known to work with your plugin version (check the plugin's peer dependencies)
  3. Shrink the failure to one file/line by linting files individually, then simplify the offending hook until the trigger syntax is obvious
  4. File an issue on facebook/react with the minimal repro, ESLint config, and package versions - the error message explicitly asks for this
  5. Unblock CI immediately with /* eslint-disable react-hooks/exhaustive-deps */ on that file, and remove it after the real fix

Example fix

// before (package.json, versions drifted apart)
"eslint-plugin-react-hooks": "^4.6.0",
"@typescript-eslint/parser": "^8.0.0"

// after (upgrade the plugin, keep the toolchain in lockstep)
"eslint-plugin-react-hooks": "^5.2.0",
"@typescript-eslint/parser": "^8.0.0"
// then: npm dedupe && npx eslint --fix-dry-run src/hooks/**
Defensive patterns

Strategy: try-catch

Try / catch

Only relevant when driving ESLint programmatically (editors, lint runners). Catch the Error, match /Unable to acquire scope for the current node/, and treat it as tooling failure: skip the file with a warning instead of failing the entire lint run, then surface the file for an upgrade/report.

Prevention

When it happens

Trigger: Running ESLint with the exhaustive-deps rule when the configured parser (e.g. @typescript-eslint/parser with unusual parserOptions, or an experimental Babel plugin) emits an AST that leaves a hook callback node without an acquireable scope. Also triggered by other ESLint plugins or custom rules that mutate/replace AST nodes before exhaustive-deps visits them, or by plugin versions that predate a fix for a specific syntax pattern.

Common situations: Upgrading eslint-plugin-react-hooks, TypeScript, or @typescript-eslint/* independently so versions drift out of compatibility; monorepos where different packages lint with different parser configs; adopting new syntax (decorators, satisfy expressions, macros) in files containing hooks.

Related errors


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/723d06e9785f4c69. Report an issue: GitHub.