-
Notifications
You must be signed in to change notification settings - Fork 30.5k
Description
Link to the code that reproduces this issue
https://github.com/bigcommerce/catalyst/tree/CATALYST-1791-upgrade-next
To Reproduce
- Clone the repository and switch to the reproduction branch:
git clone https://github.com/bigcommerce/catalyst.git cd catalyst git checkout CATALYST-1791-upgrade-next pnpm install - In core/next.config.ts, change line 6 from:
to:
import { configClient } from "./client/config-client";The key difference between the two imports is thatimport { client as configClient } from "./client";core/client/index.tshasimport { headers } from 'next/headers'at line 2, whilecore/client/config-client.tsis a duplicate that avoids that import. - Run the dev server:
pnpm run dev - Visit http://localhost:3000 → 500 error with:
InvariantError: Invariant: Expected workUnitAsyncStorage to have a store. - Revert the import back to config-client → app works normally.
Current vs. Expected behavior
Current behavior:
When next/headers is imported (even transitively, even if headers() is never called) during next.config.ts resolution in a pnpm workspace monorepo, all page renders fail with:
InvariantError: Invariant: Expected workUnitAsyncStorage to have a store. This is a bug in Next.js.
This worked fine in Next.js 15.
Expected behavior:
Importing next/headers at the top level of a module used in next.config.ts should not poison the AsyncLocalStorage context for the runtime. If the import is problematic, Next.js should either handle it gracefully or surface a clear error during config resolution rather than failing silently at render time.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.3.0: Wed Jan 28 20:53:05 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6020
Available memory (MB): 16384
Available CPU cores: 10
Binaries:
Node: 24.13.0
npm: 11.6.2
Yarn: N/A
pnpm: 10.12.4
Relevant Packages:
next: 16.1.6 // Latest available version is detected (16.1.6).
eslint-config-next: 15.5.10
react: 19.1.5
react-dom: 19.1.5
typescript: 5.8.3
Next.js Config:
output: N/AWhich area(s) are affected? (Select all that apply)
Module Resolution
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
This issue only reproduces in a pnpm workspace monorepo with a sufficiently complex dependency graph. We have been unable to reproduce it in any minimal environment:
- A non-monorepo standalone project
- A minimal pnpm workspace monorepo matching the same directory structure
- Adding
next-intl/plugin, middleware, instrumentation, and locale routing to match our setup - Matching exact pnpm version (
10.12.4) and Node.js version (24.13.0) - Using
--preserve-symlinks/--preserve-symlinks-main flags
Our debugging suggests the issue is related to Module._pathCache being populated with the symlink path (e.g., core/node_modules/next/headers.js) during next.config.ts resolution, while the runtime resolves to the real path (.pnpm/.../next/headers.js). This results in two separate AsyncLocalStorage singleton instances — one used by the config loading phase and one by the SSR runtime — so getStore() returns undefined during rendering.
This worked fine in Next.js 15 with the same monorepo structure.