fix: auto-restart dev server when .next directory is deleted#91142
Draft
fix: auto-restart dev server when .next directory is deleted#91142
Conversation
Collaborator
Failing test suitesCommit: 4890499 | About building and testing Next.js
Expand output● delete-dot-next-dir › should recover after .next is deleted (app router)
Expand output● hmr-intercept-routes › should update intercept routes via HMR |
Adds a development test that verifies the behavior when the .next directory is deleted while the Turbopack dev server is running. The test confirms that both app router and pages router routes return 500 errors and appropriate ENOENT error messages appear in the CLI output.
…ull CLI snapshots Restructure fixture to use /app -> /app/other and /pages -> /pages/other routes. Test app and pages router deletion behavior separately with beforeEach/afterEach isolation. Add full CLI output snapshots alongside deduplicated error snapshots.
Replace environment-specific absolute paths to the Next.js package directory with NEXT_DIR placeholder so snapshots are portable across different machines and CI environments.
- Replace fragile full CLI output snapshots with stable deduplicated error message arrays (first-line only, sorted, deduped) - Use next.testDir directly for path normalization instead of next.normalizeTestDirContent wrapper - Snapshots verified without NEXT_SKIP_ISOLATE to test real module resolution paths
Enable persistent filesystem cache via turbopackFilesystemCacheInDev config option. Add 5s delay after error detection to let cache read/write errors settle. Use retry for initial page loads since the server may need time to rebuild after a previous test deleted .next.
- Fix config key: turbopackFileSystemCacheForDev (not turbopackFilesystemCacheInDev) - Set TURBO_ENGINE_IGNORE_DIRTY=1 via env option so filesystem cache works even when the git repo is dirty - Wait 5s after error detection for persistent cache errors to settle - Use retry for initial page loads since server may need time to rebuild
Detect .next directory deletion at request time and trigger an automatic restart using the existing exit-code-77 restart mechanism, instead of serving broken pages with cryptic ENOENT errors.
7ce071e to
f317d1c
Compare
bgw
reviewed
Mar 10, 2026
Comment on lines
+208
to
+215
| // If the distDir was deleted, restart the dev server instead of | ||
| // serving broken pages with cryptic ENOENT errors. | ||
| if (opts.dev && !existsSync(path.join(opts.dir, config.distDir))) { | ||
| Log.warn( | ||
| `The ${(config as NextConfigComplete).distDirRoot || config.distDir} directory was removed while the dev server was running. Restarting...` | ||
| ) | ||
| process.exit(RESTART_EXIT_CODE) | ||
| } |
Member
There was a problem hiding this comment.
Would it be better to use one of the filesystem watchers we have, instead of adding work to every request?
Replace the synchronous existsSync check on every request with a fs.watch watcher on the distDir. This avoids adding work to every request and instead reacts to filesystem events when the directory is actually deleted. Addresses review feedback from bgw on #91142.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Extract shared restart logic into restartOnDistDirRemoval helper, use it.each to parametrize app/pages test cases, and remove unused fixture files that were only needed for the old per-request approach. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
Auto-restart the Next.js dev server when the
.nextdirectory is deleted while the server is running, instead of serving broken pages with cryptic ENOENT errors.Why?
When a developer deletes the
.nextdirectory during active development (e.g., to clear caches or fix a corrupt build state), the dev server enters a broken state. Requests fail with unhelpful ENOENT errors for manifests and compiled files (pages-manifest.json,routes-manifest.json,_buildManifest.js,[turbopack]_runtime.js). The developer has to manually restart the dev server to recover.How?
Detection via
fs.watch(packages/next/src/server/lib/router-server.ts):fs.watchwatcher on thedistDir(.next/devin development)distDirstill exists usingexistsSyncprocess.exit(RESTART_EXIT_CODE)(exit code 77)next-dev.tsalready handles exit code 77 by restarting the server (same mechanism used for config file changes)restartOnDistDirRemovalhelper handles both the watch callback and error event, avoiding code duplicationKey design decisions:
fs.watchfor instant detection — the server restarts as soon as the directory is removed, without waiting for a requestexistsSyncguard inside the callback prevents false positives from other filesystem events (e.g. files being written to.next)config.distDirRoot(.next) rather thanconfig.distDir(.next/dev) so it matches what the developer actually deleteddistDirdoesn't exist yet), the error is silently ignored — the server will still work, just without automatic restart on deletionTest (
test/development/app-dir/delete-dot-next-dir/):it.eachto parametrize both app router and pages router recovery after.nextdeletion.next→ watcher triggers restart → CLI shows warning + "Ready in" → page loads again after restartturbopackFileSystemCacheForDev: trueto also exercise the persistent cache code pathTURBO_ENGINE_IGNORE_DIRTY: '1'since the test environment has a dirty git repo