-
Notifications
You must be signed in to change notification settings - Fork 3.3k
fix: potential error spam during hmr, when using next.js 16 and turbopack #14502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📦 esbuild Bundle Analysis for payloadThis analysis was generated by esbuild-bundle-analyzer. 🤖
Largest pathsThese visualization shows top 20 largest paths in the bundle.Meta file: packages/next/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js
Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js
DetailsNext to the size is how much the size has increased or decreased compared with the base branch of this PR.
|
|
Thank you @AlessioGr It's a little better - number of errors is reduced (skipped duplicate) and the order of compilation changed (setTimeout). The root issue is still in Next.js clearing cache in Turbopack (but not clearing module path referrals in Node.js) when we have full page load on route group change between (frontend) <--> (payload), introduced here: But not sure if you can do anything more on your side. We would have to either force Turbopack to keep these modules in cache on route group change (like import them in Video with reproduction Reproduction for Website Template with your latest internal release + Mongo is here: BTW, the duplicated render on HRM changes is intentional to highlight issues, but I guess in this case it's good idea to prevent it :D On my prod app I get below errors many times when installed EDIT: probably AWS and Sentry errors started after your change in |
|
I tested 3 more hypothesises:
Logs with my changes in your index.js: HRM onmessage event data: {
type: 'isrManifest',
data: {
'/pl/formularz-zapytania': false,
'/admin/collections/pages/68fa3ddb5241be84a75f65e6': false
}
}
GET /api/users/me 200 in 527ms (compile: 4ms, render: 523ms)
HRM onmessage event data: { type: 'building' }
HRM onmessage event data: { type: 'serverComponentChanges', hash: '247' }
>>> HRM lastISRManifest: {
'/pl/formularz-zapytania': false,
'/admin/collections/pages/68fa3ddb5241be84a75f65e6': false
}
>>> HRM hasPayloadPaths: true
✓ Compiled in 83ms
>>> HRM generateImportMap - SKIPPED
⨯ Error: Could not find the module "[project]/src/fields/CountChars.tsx#CountChars" in the React Client Manifest. This is probably a bug in the React Server Components bundler.
at stringify (<anonymous>) {
digest: '1401159352'
}I don't know why we always have Unless you have better idea, I'm afraid that this must be fixed by Next.js. For now, dynamic import of importMap in /app/layout.ts works the best for me in dev. My testing code if you would like to try it: let lastISRManifest = null;
cached.ws = new WebSocket(process.env.PAYLOAD_HMR_URL_OVERRIDE ?? `${protocol}://localhost:${port}${prefix}${path}`);
cached.ws.onmessage = (event)=>{
if (cached.reload instanceof Promise) {
// If there is an in-progress reload in the same getPayload
// cache instance, do not set reload to true again, which would
// trigger another reload.
// Instead, wait for the in-progress reload to finish.
return;
}
if (typeof event.data === 'string') {
const data = JSON.parse(event.data);
console.log('HRM onmessage event data:', data);
// Track isrManifest messages to determine which route group triggered changes
if (data.type === 'isrManifest' && data.data) {
lastISRManifest = data.data;
}
if (// On Next.js 15, we need to check for data.action. On Next.js 16, we need to check for data.type.
data.type === 'serverComponentChanges' || data.action === 'serverComponentChanges') {
// Only trigger reload if the last ISR manifest contained payload-related paths (/admin or /api)
// This prevents unnecessary reloads when changes are from frontend route group
console.log('>>> HRM lastISRManifest:', lastISRManifest);
const hasPayloadPaths = lastISRManifest && Object.keys(lastISRManifest).some(path =>
path.includes('/admin') || path.includes('/api')
);
console.log('>>> HRM hasPayloadPaths:', hasPayloadPaths);
if (hasPayloadPaths) {
cached.reload = true;
}
}
}
}; |
|
In your repro, this even happens completely outside of HMR, when starting up a new dev server. So it is indeed completely unrelated to HMR / importmap generation. I'll try creating a minimal reproduction outside of payload for this |
|
Yes, sometimes it happens also directly after dev server start. But not always, probably depending on cache content in .next folder. HMR triggers these errors but is not causing them. When I manually reverted changes introduced by Next.js in 15.5.0 by adding back code to Ideally Next.js should e.g.
To test if it also fixes the issue for you you can in this file: & add export in |
|
BTW, I also tested new |
|
Yep you're right - I don't think this is something we can easily fix within Payload. I've opened a Next.js issue here, with a very minimal reproduction: vercel/next.js#85883 I’m looping in the Next.js team and pointing them to your analysis so they have full context. Thanks for taking the time to really get to the bottom of this! |
|
Closing this PR, as this does not fully fix the problem. |
Fixes #14419.
In a live-preview enabled page, both the admin panel and the frontend initialize their own
getPayloadinstances, each subscribing to HMR updates. In Next.js 16 with Turbopack, this setup can cause the server console to be flooded with errors like:These errors occur when an
fscall tries to access the import map during the reload process.Fix
The import map generation is now deferred using
setTimeoutand is no longer awaited. This prevents the problematic awaitedfsaccess during HMR reloads.Video that showcases this issue and the solution on the website template:
Screenshot.2025-11-05.at.19.36.10.mp4
Additional Improvements
Additionally, this PR prevents multiple reload operations from overlapping by skipping new reloads while one is already in progress.
This reduces redundant reload triggers when multiple getPayload instances are subscribed to the same HMR websocket, reducing the chance of something going wrong.