Skip to content

[BUG]: Next.js env file watchers keep Next's telemetry helper running forever after next dev stops #1235

Closed

Description

@VDrozd-Cyclis

varlock version

varlock 1.18.0 and @varlock/nextjs-integration 1.2.2, installed as @next/env through npm overrides as the docs describe. The watcher code is unchanged in 1.2.5 and on main (packages/integrations/nextjs/src/next-env-compat.ts, fs.watchFile in enableExtraFileWatchers).

Steps to reproduce

  1. Set up a Next.js 16 app (16.3.8 here) with @next/env overridden to @varlock/nextjs-integration and varlockNextConfigPlugin() in next.config.
  2. Run next dev, load any page, then stop it with Ctrl+C.
  3. Run pgrep -fl detached-flush. Next's telemetry helper (next/dist/telemetry/detached-flush.js), which next dev spawns when it stops, is still running a minute later and never exits.

A shorter reproduction without a dev server, from the app directory:

mkdir -p .next/dev && echo '[]' > .next/dev/_events_repro.json
NEXT_TELEMETRY_DISABLED=1 node node_modules/next/dist/telemetry/detached-flush.js dev . _events_repro.json

The helper consumes the events file and then keeps running.

What is expected?

After next dev stops, the telemetry helper sends its events and exits.

What is actually happening?

The helper never exits, so every next dev stop leaves one Node process behind. One developer laptop had 24 of them, some two days old.

  • Since Next 16.0.3 the helper no longer calls process.exit; it exits when nothing is pending (vercel/next.js#97716).
  • The helper loads next.config through Next's loadConfig for the development phase, which calls loadEnvConfig(dir, true). In next-env-compat, that calls enableExtraFileWatchers, which starts fs.watchFile(filePath, { interval: 500 }, …) for .env.schema and the other sources. fs.watchFile watchers are persistent by default, so they keep the helper alive.
  • claimExtraFileWatcherOwnership doesn't stop this. The next dev parent process that spawns the helper never loads the env, so __VARLOCK_NEXT_ENV_WATCHER_PID is not set in the helper's environment, and the helper claims the watchers.
  • An async_hooks dump of a stuck helper shows process.getActiveResourcesInfo() as ["StatWatcher","StatWatcher","StatWatcher"]. All three were created by enableExtraFileWatchers, called from loadEnvConfig, Next's loadConfigImpl and detached-flush.js.
  • NEXT_TELEMETRY_DISABLED=1 doesn't help, because Next spawns the helper anyway.

Suggested fix

Make the watchers non-persistent: fs.watchFile(filePath, { interval: 500, persistent: false }, …). persistent: false only stops a watcher from keeping the process alive. The dev server stays alive through its HTTP server, so env reloading keeps working, and short-lived processes such as the telemetry helper can exit. Calling unref() on the returned watcher would have the same effect.

System Info

macOS 27.0.1 (arm64) and Debian 12 (x64, in a container)
Node 24.14.0, npm 11.6.2
next 16.3.8
varlock 1.18.0, @varlock/nextjs-integration 1.2.2

Any additional comments?

As a workaround, each next.config checks whether process.argv[1] ends with telemetry/detached-flush.js. If it does, the config schedules an unref'd process.exit(0) after 30 s. A non-persistent watcher would make that unnecessary.

Activity

  1. pullfrog commented on Oct 16, 2026

    @pullfrog
    Contributor
  2. theoephraim commented on Oct 16, 2026

    @theoephraim
    Member

    thanks for the report!

  3. github-actions commented on Oct 16, 2026

    @github-actions
    Contributor

    ✅ A fix has been merged to main in #1237 and will ship in the next release. GitHub auto-closed this issue on merge, but the change isn't published yet.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions