[next-rspack] `next dev` aborts with a Rust panic when the error overlay or browser-log forwarding source-maps a frame during a rebuild
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 142k
- Forks
- 32.4k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 351
Description
Link to the code that reproduces this issue
https://github.com/Dwlad90/next-rspack-stale-compilation-repro
To Reproduce
npm install
npm run generate # 5000 tiny modules so a rebuild takes long enough to be hit
npm run repro # boots `next dev -p 3456`, edits a module, posts stack frames, repeats
The driver posts to POST /__nextjs_original-stack-frames (what the error overlay does) while
a rebuild is in flight. No browser is needed. Result on my machine:
Two runs from a clean .next: REPRODUCED after 1 trial(s) both times, attempted to read from stolen value: ...BuildModuleGraphArtifact. Control with the stack-frame posting switched off (POSTERS=0): green through 8 trials with the same edits, so the source-map request is load-bearing, not the edit alone.
Without the driver: next dev, open the page in a browser whose console shows an error (any
console.error in a client component), then append a comment to an imported file every
second. Either the overlay's stack-frame request or the forwarded console error makes the
server source-map a stack during the rebuild.
Current vs. Expected behavior
Current: the dev server dies and has to be restarted.
Panic occurred at runtime. Please file an issue on GitHub with the panic info and backtrace below: https://github.com/web-infra-dev/rspack/issues
thread '<unnamed>' panicked at /Users/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rspack_core-0.100.4/src/utils/steal_cell.rs:60:26:
attempted to read from stolen value: rspack_core::artifacts::module_ids_artifact::ModuleIdsArtifact
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
The stolen value is sometimes BuildModuleGraphArtifact instead.
Expected: a stack frame that cannot be mapped during a rebuild comes back unmapped. The dev
server keeps running.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin 25.6.0
Binaries:
Node: 24.11.0
npm: 11.x
pnpm: 11.x
Relevant Packages:
next: 16.3.3 (also 16.3.4 and 16.4.0-canary.15 pin the same @next/rspack-core 1.0.3)
next-rspack: 16.3.3
@next/rspack-core: 1.0.3 (@next/rspack-binding 1.0.3, rspack_core 0.100.4)
react: 19.2.0
react-dom: 19.2.0
typescript: 7.0.2
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Developer Experience, Rspack
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
Cause
packages/next/src/server/dev/middleware-webpack.ts reads Stats.compilation from request
handlers, outside the compile lifecycle:
getOverlayMiddleware→POST /__nextjs_original-stack-frames→getOriginalStackFramesbrowser-logs/receive-logs.ts→getSourceMappedStackFrames→mapFramesUsingBundler→
getOriginalStackFrames
Both reach getSourceMapFromCompilation → getModuleById, which does compilation.modules
and then chunkGraph.getModuleId(module) for every module until one matches.
Under webpack that is fine: a kept Stats.compilation is a JavaScript snapshot. Under rspack it
is not. The binding hands JS a raw pointer to Compiler.compilation, and Compiler::rebuild
replaces that struct in place (std::mem::replace), so the kept object aliases the compilation
being rebuilt on tokio threads. compilation.modules dereferences rspack's
StealCell<BuildModuleGraphArtifact> (stolen during make) and getModuleId dereferences
StealCell<ModuleIdsArtifact> (stolen during the module-ids hooks). Whichever pass the rebuild
is in is the artifact that panics, and the binary aborts.
The rspack side is filed separately (web-infra-dev/rspack#15451): the stale handle should fail
closed. This issue is about the host side, which is independently fixable and would also stop
the abort today.
Evidence
I wrapped every native binding accessor from JS and logged any call made while a compiler was
between watchRun and done with no compile hook on the stack. The last line before every
panic was getModuleId or compilation.modules from getModuleById, via one of the two routes
above. In one window between a client thisCompilation and the panic there were 1,096,130
getModuleId calls from that scan. Making the stale Compilation object throw kept the same
loop green through 41 trials; the baseline panicked at trials 1, 6 and 18.
Two smaller problems on the same path
logging.browserToTerminal: falsedoes not stop the forwarder from source-mapping.handleLog
still processesformatted-error/any-logged-errorentries whenever the file logger is
enabled, and the file logger is enabled byexperimental.mcpServer, which defaults totrue.
So a project that has switched browser logs off still runs this code on every browser error.getModuleByIdis a linear scan with one native call per module per frame. With a few
thousand modules and a 40-frame stack that is well over 100k native calls for one request.
Fix that works for us
Skip the lookup while the owning compiler is rebuilding. The scan is synchronous and rebuilds
only start from JavaScript, so the check is not racy:
function getModuleById(id: string | undefined, compilation: webpack.Compilation) {
// Under rspack a compilation kept from an earlier build aliases the one being rebuilt.
if (compilation.compiler?.watching?.running === true) return undefined
const { chunkGraph, modules } = compilation
return [...modules].find((module) => chunkGraph.getModuleId(module) === id)
}
Both rspack's and webpack's Watching expose running. We carry this as a pnpm patch and
the panic has not recurred; a frame requested mid-rebuild comes back unmapped and maps on the
next request.
packages/next/src/server/dev/middleware-webpack.ts on canary (2026-09-03) still has the
unguarded getModuleById.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/next/src/server/dev/middleware-webpack.ts and trace getModuleById through getOriginalStackFrames, including the overlay and browser-log routes. Run the linked reproduction with npm install, npm run generate, and npm run repro while inspecting the existing source-map behavior. Done means mid-rebuild frames return unmapped instead of aborting next dev, and later requests still map normally.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nextjs, node.js
- Domain
- build-system, developer-experience, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100