You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Control: npm install next@16.2.11 && rm -rf .next && npm run build on the same project succeeds, so this is a 16.3.0 regression.
Current vs. Expected behavior
Current:next build crashes with a fatal Turbopack panic:
Error [TurbopackInternalError]: reading file "/private/tmp/nft-symlink-repro/data/dir-link"
Caused by:
- Is a directory (os error 21)
Debug info:
- Execution of emit_all_output_assets_once_with_issues_operation failed
- Execution of EntrypointsOperation::new failed
- Execution of emit_all_output_assets_once_operation failed
- Execution of Project::emit_all_output_assets failed
- Execution of emit_assets failed
- Execution of emit failed
- Execution of <NftJsonAsset as Asset>::content failed
- Execution of *FileContent::hash failed
- Execution of <DiskFileSystem as FileSystem>::read failed
- reading file "/private/tmp/nft-symlink-repro/data/dir-link"
- Is a directory (os error 21)
Expected: the build succeeds, as it does on 16.2.11 — a symlink to a directory inside a traced/included path should be traversed or skipped, not treated as a regular file.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.6.0
Available memory (MB): 36864
Available CPU cores: 12
Binaries:
Node: 24.13.0
npm: 11.6.2
Yarn: N/A
pnpm: 11.9.0
Relevant Packages:
next: 16.3.0 // Latest available version is detected (16.3.0).
eslint-config-next: N/A
react: 19.2.0
react-dom: 19.2.0
typescript: 6.0.2
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Turbopack, Output (export/standalone)
Which stage(s) are affected? (Select all that apply)
next build (local), Vercel (Deployed)
Additional context
Root cause, from reading the v16.3.0 source:
crates/next-api/src/nft.rs (get_glob_includes, around L198) classifies glob results with:
read() on a symlink-to-directory fails with EISDIR, which surfaces as a fatal TurbopackInternalError.
On 16.2 the misclassified entry was only listed in the .nft.json, so it was harmless; the unconditional hashing added in 16.3 turns it into a build-breaking panic. The same DirectoryEntry::File | DirectoryEntry::Symlink pattern is still present on current canary, so canary is affected too.
Notes:
outputFileTracingExcludes does not work around this — the panic happens while hashing the includes collection, before excludes are relevant.
In pnpm monorepos no unusual config is needed to hit this: any workspace package listed in serverExternalPackages whose node_modules contains a workspace link (pnpm creates node_modules/@scope/pkg → ../../sibling directory symlinks) crashes the same way. That's how we originally hit it in a production monorepo; the only workaround was removing the dependency so the symlink no longer exists.
Link to the code that reproduces this issue
https://github.com/rollokd/next-turbopack-nft-symlink-eisdir
To Reproduce
npm installnpm run buildThe repro is intentionally tiny: a fresh app-router app plus
data/dir-link— a symlink pointing at the directorydata/real-dir(committed as a symlink)outputFileTracingIncludesglob that matches it:Control:
npm install next@16.2.11 && rm -rf .next && npm run buildon the same project succeeds, so this is a 16.3.0 regression.Current vs. Expected behavior
Current:
next buildcrashes with a fatal Turbopack panic:Expected: the build succeeds, as it does on 16.2.11 — a symlink to a directory inside a traced/included path should be traversed or skipped, not treated as a regular file.
Provide environment information
Which area(s) are affected? (Select all that apply)
Turbopack, Output (export/standalone)
Which stage(s) are affected? (Select all that apply)
next build (local), Vercel (Deployed)
Additional context
Root cause, from reading the v16.3.0 source:
crates/next-api/src/nft.rs(get_glob_includes, around L198) classifies glob results with:Every symlink is pushed into the includes list as if it were a file — the symlink target's type is never checked.
crates/next-api/src/nft_json.rs(NftJsonAsset::content) — new in 16.3 — content-hashes every include for the newfileHashesfield:read()on a symlink-to-directory fails with EISDIR, which surfaces as a fatalTurbopackInternalError.On 16.2 the misclassified entry was only listed in the
.nft.json, so it was harmless; the unconditional hashing added in 16.3 turns it into a build-breaking panic. The sameDirectoryEntry::File | DirectoryEntry::Symlinkpattern is still present on current canary, so canary is affected too.Notes:
outputFileTracingExcludesdoes not work around this — the panic happens while hashing the includes collection, before excludes are relevant.serverExternalPackageswhosenode_modulescontains a workspace link (pnpm createsnode_modules/@scope/pkg → ../../siblingdirectory symlinks) crashes the same way. That's how we originally hit it in a production monorepo; the only workaround was removing the dependency so the symlink no longer exists.