chore(frontend): log chunk preload failures to Datadog - #9847
Open
kevin9foong wants to merge 1 commit into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds client-side telemetry for Vite lazy-route chunk preload failures by registering a vite:preloadError listener and reporting the error context to Datadog (observe-only; no recovery behavior).
Changes:
- Register
registerChunkPreloadErrorLogger()early in the app bootstrap. - Add a new
chunkPreloadErrormodule to detect “public form” routes and log preload failures to Datadog. - Add unit tests covering pathname classification, logging payload, non-suppression, and unregister behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| apps/frontend/src/index.tsx | Registers the preload error logger before React render so early lazy imports are observed. |
| apps/frontend/src/app/chunkPreloadError.ts | Implements the Vite vite:preloadError event handler + public-form pathname detection + Datadog logging. |
| apps/frontend/src/app/chunkPreloadError.test.ts | Adds Vitest coverage for route matching, logging payload, and listener lifecycle. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+46
to
+57
| datadogLogs.logger.error('Chunk preload failed', { | ||
| meta: { | ||
| action: 'chunk-preload-failed', | ||
| pathname: window.location.pathname, | ||
| version: import.meta.env.VITE_APP_VERSION, | ||
| isPublicForm: isPublicFormPathname(window.location.pathname), | ||
| error: { | ||
| message: event.payload?.message, | ||
| stack: event.payload?.stack, | ||
| }, | ||
| }, | ||
| }) |
Comment on lines
+18
to
+23
| const setPathname = (pathname: string) => { | ||
| Object.defineProperty(window, 'location', { | ||
| configurable: true, | ||
| value: { pathname }, | ||
| }) | ||
| } |
Comment on lines
+18
to
+19
| registerChunkPreloadErrorLogger() | ||
|
|
A lazy route chunk that fails to load leaves the app blank, and we have no telemetry for it today, so we cannot tell whether it happens at all. Two causes are plausible. A tab left open across a deploy requests a hash that is no longer on the container's disk — already mitigated by catchNonExistentStaticRoutesMiddleware falling back to the S3 static assets bucket. Or Cloudflare issues a cf-mitigated challenge for the chunk request itself: the interstitial comes back as HTML, the browser rejects the module, and nothing catches it, because we only handle challenges for API calls in the ApiService interceptor and a dynamic import() is a plain browser fetch that axios never sees. This observes only. The handler does not call preventDefault(), so Vite still rethrows and existing error reporting is unchanged. Recovery — a reload is the only client-side option for the challenge case — waits until the logs say whether it is warranted, and how often. The pathname is logged as isPublicForm because a respondent-facing failure is more severe than an admin one, and any future recovery would have to treat the two differently. The registration returns an unregister function. The app never calls it — the handler lives as long as the page — but without it every test in the suite leaks a listener onto the shared jsdom window. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
kevin9foong
force-pushed
the
chore/log-vite-preload-error
branch
from
August 13, 2026 06:10
74d7301 to
84e87e6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A lazy route chunk that fails to load leaves the app blank, and we have no telemetry for it today — so we cannot tell whether it is actually happening, how often, or to whom.
What this does
Registers a
vite:preloadErrorlistener that logs to Datadog and does nothing else.Deliberately observe-only:
preventDefault(), so Vite still rethrows and existing error reporting is unchanged.Logged fields:
pathname,isPublicForm, appversion, and the error message/stack.isPublicFormas any future recovery would have to treat the two differently (a reload would discard a half-filled form).Notes for the reviewer
registerChunkPreloadErrorLoggerreturns an unregister function. The app never calls it — the handler lives as long as the page — but tests need it so listeners do not accumulate on the shared jsdom window./:formId([a-fA-F0-9]{24})infrontend.routes.ts.Tests
apps/frontend/src/app/chunkPreloadError.test.ts— 8 tests, passing. Covers the pathname matcher, the logged payload, the public form flag, that the rethrow is not suppressed, and that unregistering stops handling.