Description
Link to the code that reproduces this issue
https://github.com/Lisenish/next-15-instrumentation-issue-mre
To Reproduce
- Clone the repository and run
npm install
. - Execute
npm run build
- Execute
next start
. - Observe the logs and outputs in the console and observe the behavior in the browser
- Switch git branch to
next-14-version
- Do steps 2,3,4 for this branch and compare the behavior
Current vs. Expected behavior
Next.js 15.x (Regression)
In Next.js 15.x, side effect files appear to execute before instrumentation file complete its execution. This causes environment variables or state setup in the instrumentation file to be unavailable during the side effect execution.
You can see in logs that we have the log line Running global side effect file.
while instrumentation file didn't finish the execution
Logs:
next start
▲ Next.js 15.3.1-canary.4
- Local: http://localhost:3000
- Network: http://10.100.10.23:3000
✓ Starting...
Loading environment variables
✓ Ready in 245ms
Running global side effect file.
process.env.SOME_GSM_SECRET outside: undefined
Environment variables are loaded
process.env.SOME_GSM_SECRET in instrumentation: mocked secret value
Running in function to get secret value dynamically.
process.env.SOME_GSM_SECRET inside function: mocked secret value
On the app side it results in static value in global var not being set correctly, and it shows "no set value"
Next.js 14.x (Expected Behavior)
Instrumentation files should fully run before other files (e.g., global side effect files) dependent on their side effects. This was the behavior in Next.js 14.x and is the expected behavior.
Logs shows it runs as expected (instrumentation load finishes before any attempts to execute side effects in other files)
> next start
▲ Next.js 14.2.27
- Local: http://localhost:3000
✓ Starting...
Loading environment variables
✓ Ready in 156ms
Environment variables are loaded
process.env.SOME_GSM_SECRET in instrumentation: mocked secret value
--- I opened the page in browser ---
Running global side effect file.
process.env.SOME_GSM_SECRET outside: mocked secret value
Running in function to get secret value dynamically.
process.env.SOME_GSM_SECRET inside function: mocked secret value
On the app side both values are present:
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 24.3.0: Thu Jan 2 20:24:23 PST 2025; root:xnu-11215.81.4~3/RELEASE_ARM64_T6031
Available memory (MB): 36864
Available CPU cores: 14
Binaries:
Node: 23.11.0
npm: 10.9.2
Yarn: N/A
pnpm: 10.8.0
Relevant Packages:
next: 15.3.1-canary.4 // Latest available version is detected (15.3.1-canary.4).
eslint-config-next: N/A
react: 19.1.0
react-dom: 19.1.0
typescript: 5.8.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Instrumentation
Which stage(s) are affected? (Select all that apply)
next start (local), Other (Deployed)
Additional context
No response