Skip to content

fix(@next/env): include dir in cache key for loadEnvConfig#92061

Open
sleitor wants to merge 1 commit intovercel:canaryfrom
sleitor:fix-92040
Open

fix(@next/env): include dir in cache key for loadEnvConfig#92061
sleitor wants to merge 1 commit intovercel:canaryfrom
sleitor:fix-92040

Conversation

@sleitor
Copy link
Copy Markdown
Contributor

@sleitor sleitor commented Mar 28, 2026

Problem

loadEnvConfig in @next/env uses module-level variables to cache the result. The cache guard:

if (combinedEnv && !forceReload) {
  return { combinedEnv, parsedEnv, loadedEnvFiles: cachedLoadedEnvFiles }
}

ignores the dir argument — so when Next.js internally calls loadEnvConfig (with the app directory) before user code runs, then user code calls loadEnvConfig with a different directory (e.g. a monorepo root), the cache returns the previous result for the wrong directory with no warning or error.

This is especially common in monorepo setups where .env files live in a parent directory outside the Next.js app.

Fixes #92040

Fix

Add a cachedDir module-level variable and include it in the cache check:

if (combinedEnv && !forceReload && cachedDir === dir) {
  return { combinedEnv, parsedEnv, loadedEnvFiles: cachedLoadedEnvFiles }
}

cachedDir is updated whenever a fresh load is performed. The existing forceReload: true workaround continues to work.

Testing

Added test/unit/load-env-cache-dir.test.ts covering:

  • Distinct directories load their respective .env files
  • Different dir without forceReload is no longer silently cached from previous dir
  • Same dir without forceReload still correctly uses the cache

When Next.js internally calls loadEnvConfig before user code runs,
the result is cached in module-level variables. The cache check:

  if (combinedEnv && !forceReload)

ignored the `dir` argument, so user code calling loadEnvConfig with
a different directory (e.g. the monorepo root) would silently receive
the cached result for the original directory instead of loading env
files from the requested path.

Fix: add a `cachedDir` module-level variable and include it in the
cache guard so the cache is only reused when the same directory is
requested:

  if (combinedEnv && !forceReload && cachedDir === dir)

The existing workaround of passing `forceReload: true` continues
to work unchanged.

Closes vercel#92040
@nextjs-bot
Copy link
Copy Markdown
Collaborator

Allow CI Workflow Run

  • approve CI run for commit: f43e83c

Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

loadEnvConfig silently ignores directory argument in monorepo due to internal cache

2 participants