nextjs - 💡(How to fix) Fix next/dynamic lazy chunk uses stale module graph after source edits (Turbopack) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#93293Fetched 2026-04-28 06:23:23
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
labeled ×1

Error Message

  • Crash: Error: Module factory is not available. It might have been deleted in an HMR update.
  1. Structural hydration mismatch triggers React 19 error recovery

Fix Action

Fix / Workaround

Workaround: Replace next/dynamic with a static import — confirms the issue is specific to the lazy chunk path in Turbopack.

Code Example

- const ItemCard = dynamic(() => import("./ItemCard"), { ssr: false })
+ import ItemCard from "./ItemCard"

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.6.0
  Available memory (MB): 65536
  Available CPU cores: 12
Binaries:
  Node: 22.14.0
  npm: 10.9.2
  Yarn: N/A
  pnpm: 10.5.2
Relevant Packages:
  next: 16.1.6
  eslint-config-next: N/A
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.8.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/Djangologie/turbopack-dynamic-stale-chunk-repro

To Reproduce

  1. npm install && npm run dev (Turbopack)
  2. Open http://localhost:3000, click "Seed 12 items" — cards render with [CATEGORY] prefix
  3. Edit src/lib/format-utils.ts: change [${cat.toUpperCase()}] to >> ${cat.toUpperCase()} <<
  4. Save the file

Expected: HMR updates the cards to show the new format.

Actual: One of:

  • Cards still show old format [REACT] (stale chunk — hash unchanged)
  • Crash: TypeError: formatCategory is not a function (module factory evicted but chunk not re-linked)
  • Crash: Error: Module factory is not available. It might have been deleted in an HMR update.

The stale chunk persists across hard refresh, rm -rf .next + server restart, and even full node_modules reinstall. Only next build (Webpack) resolves it.

Additional context

This compounds severely with persisted Zustand stores (see src/stores/item-store.ts):

  1. First visit: store empty → SSR and client match → no issue
  2. User seeds items → persisted to localStorage
  3. Page reload: server renders 0 items, client hydrates with 12 items from localStorage
  4. Structural hydration mismatch triggers React 19 error recovery
  5. Combined with stale dynamic chunk, recovery produces corrupted DOM: NaN of NaN pagination, missing CSS classes, broken refs

Workaround: Replace next/dynamic with a static import — confirms the issue is specific to the lazy chunk path in Turbopack.

- const ItemCard = dynamic(() => import("./ItemCard"), { ssr: false })
+ import ItemCard from "./ItemCard"

next build + next start works correctly in all cases.

Current vs. Expected behavior

Current: next/dynamic chunks in Turbopack retain stale module references after source edits. The chunk hash does not update, so browsers serve cached stale code indefinitely.

Expected: Editing a module imported by a dynamically-loaded component should invalidate the lazy chunk and generate a new hash, just like Webpack does in production builds.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.6.0
  Available memory (MB): 65536
  Available CPU cores: 12
Binaries:
  Node: 22.14.0
  npm: 10.9.2
  Yarn: N/A
  pnpm: 10.5.2
Relevant Packages:
  next: 16.1.6
  eslint-config-next: N/A
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.8.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Turbopack

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

This was originally filed as #93292 and closed by the bot for missing a reproduction link. This is the re-filed version with a complete minimal reproduction.

extent analysis

TL;DR

Replace next/dynamic with a static import or use next build to resolve the stale chunk issue in Turbopack.

Guidance

  • Verify that the issue is specific to the lazy chunk path in Turbopack by replacing next/dynamic with a static import, as shown in the provided workaround.
  • Check if the chunk hash updates after editing a module imported by a dynamically-loaded component.
  • Consider using next build and next start as a temporary workaround to ensure correct behavior.
  • Investigate the differences in how Turbopack and Webpack handle dynamic imports and chunk updates.

Example

- const ItemCard = dynamic(() => import("./ItemCard"), { ssr: false })
+ import ItemCard from "./ItemCard"

Notes

The issue seems to be specific to Turbopack and next/dynamic imports. The provided workaround confirms this. However, a more permanent solution would require understanding why Turbopack is not updating the chunk hash after source edits.

Recommendation

Apply the workaround by replacing next/dynamic with a static import, as it confirms the issue is specific to the lazy chunk path in Turbopack and provides a reliable solution.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - 💡(How to fix) Fix next/dynamic lazy chunk uses stale module graph after source edits (Turbopack) [1 participants]