Skip to content

[WEB-8632] fix(web): auto-reload on stale chunk load failure during navigation - #9579

Merged
sriramveeraghanta merged 2 commits into
previewfrom
fix/web-8632-stale-chunk-reload
Aug 10, 2026
Merged

[WEB-8632] fix(web): auto-reload on stale chunk load failure during navigation#9579
sriramveeraghanta merged 2 commits into
previewfrom
fix/web-8632-stale-chunk-reload

Conversation

@codingwolf-at

@codingwolf-at codingwolf-at commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

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 a window.error/unhandledrejection event — only the app's root ErrorBoundary. 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):

  • Added 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's dataStrategy wrapper message) and exposes a reload-once-then-fall-back-to-boundary guard.
  • entry.client.tsx: production-only vite:preloadError / error / unhandledrejection listeners trigger recovery for the raw browser-level failures.
  • root.tsx: the root ErrorBoundary now also recognizes the RR7-synthesized error and recovers the same way, since that's the only place this specific failure surfaces.
  • A repeat failure within 30s of the last reload (tracked via 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

  • Bug fix (non-breaking change which fixes an issue)

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.
  • oxlint clean on all touched files.
  • Verified root.tsx's ErrorBoundary (which also runs during SSR, unlike entry.client.tsx) doesn't crash the server render: sessionStorage access is wrapped in try/catch and treats an unavailable storage as "recently reloaded," short-circuiting before window.location.reload() is ever called.
  • Confirmed no other listener in the app already handles vite:preloadError / error / unhandledrejection, so no double-handling.
  • Manually reproduced the crash pattern (nav-switch during a simulated stale-chunk failure) and confirmed the page recovers via reload instead of showing the dead-end error screen.

References

Summary by CodeRabbit

  • Bug Fixes
    • Improved recovery from stale or outdated browser assets after deployments.
    • Automatically reloads the page once when stale asset errors are detected.
    • Detects stale asset failures during loading, rendering, and background requests.
    • Prevents repeated reload loops and falls back to the existing error screen when recovery is unavailable.
    • Preserves normal application startup and behavior when no stale asset issue is present.

…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.
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit a796adb.

@codingwolf-at codingwolf-at changed the title fix(web): implement stale asset recovery in entry client and error bo… [WEB-8632] fix(web): auto-reload on stale chunk load failure during navigation Aug 10, 2026
@makeplane

makeplane Bot commented Aug 10, 2026

Copy link
Copy Markdown

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a24cca54-a4dd-4b7b-abfe-46a3f69e0768

📥 Commits

Reviewing files that changed from the base of the PR and between 0b848c5 and a796adb.

📒 Files selected for processing (2)
  • apps/web/app/entry.client.tsx
  • apps/web/core/lib/stale-asset-error.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/app/entry.client.tsx
  • apps/web/core/lib/stale-asset-error.ts

📝 Walkthrough

Walkthrough

Production 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.

Changes

Stale asset recovery

Layer / File(s) Summary
Detection and guarded recovery
apps/web/core/lib/stale-asset-error.ts
Adds stale-asset signatures, error detection helpers, session-based reload tracking, and guarded page reload behavior.
Client error event recovery
apps/web/app/entry.client.tsx
Adds production-only handling for Vite preload errors, runtime errors, and unhandled promise rejections. Matching errors invoke stale-asset recovery.
Error boundary recovery
apps/web/app/root.tsx
Checks production errors for stale assets and attempts recovery before rendering CustomErrorComponent.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: sriramveeraghanta

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
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the web fix for automatic reloads after stale chunk load failures during navigation.
Description check ✅ Passed The description covers the change, bug-fix type, testing, screenshots status, references, root cause, and recovery behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/web-8632-stale-chunk-reload

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 31853ab and 0b848c5.

📒 Files selected for processing (3)
  • apps/web/app/entry.client.tsx
  • apps/web/app/root.tsx
  • apps/web/core/lib/stale-asset-error.ts

Comment thread apps/web/app/entry.client.tsx Outdated
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.
@sriramveeraghanta
sriramveeraghanta merged commit 1c8a60f into preview Aug 10, 2026
14 checks passed
@sriramveeraghanta
sriramveeraghanta deleted the fix/web-8632-stale-chunk-reload branch August 10, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants