Describe the bug
After upgrading to v4.0.2, the Core Config editor route can get stuck.
When opening /dashboard/#/nodes/cores/{id}, the URL changes, but the editor UI does not render. In my case, Chrome DevTools Console may show no useful runtime error. Chrome DevTools Issues only reports unrelated form/accessibility warnings, such as missing id/name/autocomplete or label mismatch, but those warnings do not explain the route not rendering.
The likely problem is in chunk-recovery.ts: vite:preloadError is always suppressed with event.preventDefault(), even when recoverFromChunkLoadError(...) does not actually recover/reload.
https://github.com/PasarGuard/panel/blob/v4.0.2/dashboard/src/utils/chunk-recovery.ts#L92-L99
Vite docs say that calling event.preventDefault() prevents the preload error from being thrown:
https://vite.dev/guide/build#load-error-handling
The Core Config editor route is lazy-loaded here:
https://github.com/PasarGuard/panel/blob/v4.0.2/dashboard/src/app/router.tsx#L7-L12
And mounted here:
https://github.com/PasarGuard/panel/blob/v4.0.2/dashboard/src/app/router.tsx#L130-L151
lazyWithChunkRecovery returns await importer() directly and does not validate that the resolved module contains a valid default export:
https://github.com/PasarGuard/panel/blob/v4.0.2/dashboard/src/utils/chunk-recovery.ts#L108-L121
React lazy() expects the promise to resolve to an object with a valid .default component:
https://react.dev/reference/react/lazy
To Reproduce
Steps to reproduce the behavior:
- Upgrade panel to
v4.0.2.
- Open the dashboard in Chrome.
- Go to
Nodes.
- Open
Core Configs.
- Click any existing core config.
- URL changes to
/dashboard/#/nodes/cores/{id}.
- The Core Config editor does not render / page stays stuck.
- Console may be empty because the preload error is suppressed.
Expected behavior
The Core Config editor should render normally after opening /dashboard/#/nodes/cores/{id}.
If a stale or broken chunk is detected, the app should either reload/recover or surface the real error in the console. It should not silently suppress the preload error and leave the route stuck.
Machine details (please complete the following information):
- Server OS: Ubuntu 24.04
- Deployment: Docker Compose
- Panel version:
v4.0.2
- Browser: Chrome on Windows 11
Additional context
Suggested fix: only call event.preventDefault() if recovery actually starts:
window.addEventListener('vite:preloadError', (event) => {
const preloadError =
'payload' in event
? (event as Event & { payload: unknown }).payload
: (event as CustomEvent<unknown>).detail
if (recoverFromChunkLoadError(preloadError ?? event)) {
event.preventDefault()
}
})
Also validate the lazy-loaded module shape
importer: () => Promise<{ default: T }>,
) {
return lazy(async () => {
try {
const module = await importer()
if (!module || typeof module !== 'object' || !('default' in module)) {
throw new Error('Lazy chunk resolved without a default export')
}
return module
} catch (error) {
if (recoverFromChunkLoadError(error)) {
return new Promise<{ default: T }>(() => undefined)
}
throw error
}
})
}
Describe the bug
After upgrading to
v4.0.2, the Core Config editor route can get stuck.When opening
/dashboard/#/nodes/cores/{id}, the URL changes, but the editor UI does not render. In my case, Chrome DevTools Console may show no useful runtime error. Chrome DevTools Issues only reports unrelated form/accessibility warnings, such as missingid/name/autocompleteor label mismatch, but those warnings do not explain the route not rendering.The likely problem is in
chunk-recovery.ts:vite:preloadErroris always suppressed withevent.preventDefault(), even whenrecoverFromChunkLoadError(...)does not actually recover/reload.https://github.com/PasarGuard/panel/blob/v4.0.2/dashboard/src/utils/chunk-recovery.ts#L92-L99
Vite docs say that calling
event.preventDefault()prevents the preload error from being thrown:https://vite.dev/guide/build#load-error-handling
The Core Config editor route is lazy-loaded here:
https://github.com/PasarGuard/panel/blob/v4.0.2/dashboard/src/app/router.tsx#L7-L12
And mounted here:
https://github.com/PasarGuard/panel/blob/v4.0.2/dashboard/src/app/router.tsx#L130-L151
lazyWithChunkRecoveryreturnsawait importer()directly and does not validate that the resolved module contains a validdefaultexport:https://github.com/PasarGuard/panel/blob/v4.0.2/dashboard/src/utils/chunk-recovery.ts#L108-L121
React
lazy()expects the promise to resolve to an object with a valid.defaultcomponent:https://react.dev/reference/react/lazy
To Reproduce
Steps to reproduce the behavior:
v4.0.2.Nodes.Core Configs./dashboard/#/nodes/cores/{id}.Expected behavior
The Core Config editor should render normally after opening
/dashboard/#/nodes/cores/{id}.If a stale or broken chunk is detected, the app should either reload/recover or surface the real error in the console. It should not silently suppress the preload error and leave the route stuck.
Machine details (please complete the following information):
v4.0.2Additional context
Suggested fix: only call
event.preventDefault()if recovery actually starts:Also validate the lazy-loaded module shape