[WEB-8632] fix(web): auto-reload on stale chunk load failure during navigation - #9579
Conversation
…undary Added event listeners in entry.client.tsx to handle stale asset errors in production, allowing for recovery from stale assets. Updated the ErrorBoundary component in root.tsx to utilize the same recovery mechanism for stale chunk failures, enhancing error handling and user experience.
|
React Doctor found no new issues. 🎉 Reviewed by React Doctor for commit |
|
Linked to Plane Work Item(s) This comment was auto-generated by Plane |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughProduction stale-asset detection and recovery were added to the web client. Matching preload, runtime, promise, and error-boundary failures trigger a guarded page reload once within 30 seconds. ChangesStale asset recovery
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant Browser
participant ClientEntry
participant ErrorBoundary
participant stale-asset-error
participant sessionStorage
Browser->>ClientEntry: emit preload, runtime, or rejection error
ClientEntry->>stale-asset-error: detect stale asset
stale-asset-error->>sessionStorage: check reload timestamp
stale-asset-error->>Browser: reload once when outside 30-second window
Browser->>ErrorBoundary: report remaining failure
ErrorBoundary->>stale-asset-error: detect stale asset
ErrorBoundary->>Browser: render CustomErrorComponent when recovery is not allowed
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/app/entry.client.tsx`:
- Around line 19-21: Update the vite:preloadError listener in
apps/web/app/entry.client.tsx (lines 19-21) to call recoverFromStaleAsset only
for a matching stale-asset event and invoke preventDefault only when recovery
reports that it initiated a reload. Update recoverFromStaleAsset in
apps/web/core/lib/stale-asset-error.ts (lines 46-62) to return a boolean
indicating whether reload recovery succeeded; return false when the guard or
sessionStorage path fails, preserving Vite’s default error handling.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 252d9af6-339a-40ed-90f3-cfbfb0b425bd
📒 Files selected for processing (3)
apps/web/app/entry.client.tsxapps/web/app/root.tsxapps/web/core/lib/stale-asset-error.ts
Refactored the recoverFromStaleAsset function to return a boolean indicating whether a reload was triggered, enhancing the handling of stale asset errors. Updated the event listener in entry.client.tsx to prevent default behavior only when a recovery is in progress, improving error management in production environments.
Description
Customers on self-hosted CE (and Cloud) reported full-page crashes when switching between projects or views in the nav bar (e.g. Overview → Work Items), reliably reproducible and only recoverable with a manual reload.
Root cause: after a new deploy rotates hashed asset filenames, a browser tab still on the old build fails to lazy-load the next route's JS chunk on client-side navigation. React Router 7 wraps that failure into its own generic error (
No result returned from dataStrategy for route ...), which never reaches awindow.error/unhandledrejectionevent — only the app's rootErrorBoundary. The app had no stale-chunk recovery at all, so this fell straight through to the dead-end "Looks like something went wrong" page.Fix (ported from the equivalent fix already shipped in
plane-ee#8781, adapted for CE which has no Sentry/telemetry to report to):apps/web/core/lib/stale-asset-error.ts: recognizes known stale-asset signatures (Chromium/Firefox/Safari dynamic-import failures, Vite CSS preload failures, and RR7'sdataStrategywrapper message) and exposes a reload-once-then-fall-back-to-boundary guard.entry.client.tsx: production-onlyvite:preloadError/error/unhandledrejectionlisteners trigger recovery for the raw browser-level failures.root.tsx: the rootErrorBoundarynow also recognizes the RR7-synthesized error and recovers the same way, since that's the only place this specific failure surfaces.sessionStorage) falls through to the normal error page instead of reload-looping, so a genuine (non-deploy-related) loader bug still surfaces to the user.Type of Change
Screenshots and Media (if applicable)
N/A — error-recovery/event-plumbing fix, no visual change.
Test Scenarios
pnpm run check:types(react-router typegen + tsc --noEmit) clean on the full web app.oxlintclean on all touched files.root.tsx'sErrorBoundary(which also runs during SSR, unlikeentry.client.tsx) doesn't crash the server render:sessionStorageaccess is wrapped in try/catch and treats an unavailable storage as "recently reloaded," short-circuiting beforewindow.location.reload()is ever called.vite:preloadError/error/unhandledrejection, so no double-handling.References
Summary by CodeRabbit