Feature: lazy load reload#297
Conversation
📝 WalkthroughWalkthroughAdds a React/webpack chunk-load recovery utility with per-build reload protection, global error handling, Sentry filtering, Jest coverage, a Webpack entry, and a package version update. ChangesChunk Error Recovery
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant ReactLazy
participant lazyWithReload
participant sessionStorage
participant Window
participant Sentry
ReactLazy->>lazyWithReload: import module
lazyWithReload->>sessionStorage: check build reload state
lazyWithReload->>Window: reload on matching chunk error
Window->>lazyWithReload: repeated failure after reload
lazyWithReload->>Sentry: report recovery failure
🚥 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: 4
🤖 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 `@src/utils/lazy-with-reload.js`:
- Around line 40-55: Update isHtmlParsedAsScriptError to recognize Firefox’s
SyntaxError wording, “expected expression, got '<',” in addition to the existing
“Unexpected token '<'” check. Preserve the existing SyntaxError detection and
filename pattern guard, while allowing either characteristic message to trigger
the stale-chunk fallback.
- Around line 124-143: Update reloadOnChunkError to track, in memory, whether a
reload has already been triggered during the current page lifecycle or tick
before consulting persisted reload state. Have subsequent concurrent chunk
failures return without calling reportRecoveryFailed, while preserving the
existing persisted-state check for failures occurring after navigation and the
current write/sessionStorage/reload flow for the first failure.
- Around line 210-224: Update chunkErrorSentryBeforeSend to extract the relevant
filename from each Sentry exception’s stack frames and pass it with the
exception type and value to isChunkLoadError. Preserve the existing filtering
behavior for genuine chunk-load errors while ensuring the HTML-as-script
SyntaxError path requires a filename matching chunkFilenamePattern.
- Around line 61-82: Compute and cache the build fingerprint eagerly during
module evaluation, before any lazy chunks can load, instead of initializing
cachedBuildFingerprint inside getBuildFingerprint. Keep getBuildFingerprint as a
read-only accessor and preserve the existing document-scripts fingerprinting and
non-browser fallback behavior.
🪄 Autofix (Beta)
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: a5f6667e-34d6-40cb-a728-10d5b64ff9b6
📒 Files selected for processing (4)
package.jsonsrc/utils/__tests__/lazy-with-reload.test.jssrc/utils/lazy-with-reload.jswebpack.common.js
| const isHtmlParsedAsScriptError = ( | ||
| error, | ||
| filename, | ||
| chunkFilenamePattern = DEFAULT_CHUNK_FILENAME_PATTERN | ||
| ) => { | ||
| const message = (error && error.message) || (typeof error === "string" ? error : ""); | ||
| // "SyntaxError" can show up on error.name (a real SyntaxError object) or | ||
| // inline in the message text (window.onerror's flat event.message string, | ||
| // e.g. "Uncaught SyntaxError: Unexpected token '<'") - check both. | ||
| const looksLikeSyntaxError = | ||
| (error && error.name === "SyntaxError") || /SyntaxError/i.test(message); | ||
| if (!looksLikeSyntaxError || !/Unexpected token '<'/i.test(message)) { | ||
| return false; | ||
| } | ||
| return !filename || chunkFilenamePattern.test(filename); | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate file =="
fd -a 'lazy-with-reload\.js$' . || true
echo "== file excerpts =="
if [ -f src/utils/lazy-with-reload.js ]; then
sed -n '1,120p' src/utils/lazy-with-reload.js
fi
echo "== usages of isHtmlParsedAsScriptError =="
rg -n "isHtmlParsedAsScriptError|ChunkLoadError|chunkFilenamePattern" -S .Repository: OpenStackweb/openstack-uicore-foundation
Length of output: 8885
🌐 Web query:
Mozilla Firefox expected expression got '<' SyntaxError parsing HTML as script
💡 Result:
The error "SyntaxError: expected expression, got '<'" in Mozilla Firefox when parsing a script file occurs because the browser expected valid JavaScript code but instead received HTML content [1][2]. When the browser requests a script file, the server is supposed to return JavaScript code [3][4]. If the file path is incorrect, or if the server configuration is set up to return an HTML page (such as an index.html file or a 404 error page) for all requests, the browser receives the HTML document instead [3][4][5]. Because HTML begins with characters like "<" (e.g., in ), the JavaScript parser throws a SyntaxError when it encounters this unexpected character [3][2][4]. Common causes include: * Incorrect File Paths: The script tag uses a relative path that does not resolve correctly on the server, causing the server to return a 404 page (HTML) instead of the requested script [2][6]. * Server Routing Issues: Web servers (such as those configured with Express.js or similar frameworks) may be configured to serve index.html for all requests, often done to support Single Page Applications (SPAs) [3][4][7]. If the catch-all route is not correctly configured to exclude static assets like.js or.css files, it will return the HTML index file for every missing or misrouted asset [4][7]. * Incorrect MIME Types: Even if the file is found, if the server sends the file with a text/html MIME type rather than text/javascript, Firefox may refuse to execute it or attempt to parse it incorrectly [1][8]. To debug and resolve the issue: 1. Open the Network tab in your browser's Developer Tools [2][5]. 2. Refresh the page and locate the request for the script file that is failing [5]. 3. Check the response content of that request; if it contains HTML (like ), the server is failing to find your script and is returning a different page instead [4][5]. 4. Verify your file paths, ensure your server's static file middleware is correctly configured, and confirm that your routing rules properly handle static assets rather than catching all requests with the main HTML file [4][7][5].
Citations:
- 1: https://stackoverflow.com/questions/77832538/react-uncaught-syntaxerror-expected-expression-got-although-mime-type-is
- 2: https://www.exchangetuts.com/understanding-the-error-syntaxerror-expected-expression-got-1640985243512838
- 3: https://stackoverflow.com/questions/51668589/syntaxerror-expected-expression-got-error-vue
- 4: https://stackoverflow.com/questions/28894074/syntaxerror-expected-expression-got
- 5: https://stackoverflow.com/questions/31067531/syntaxerror-expected-expression-got-on-heroku
- 6: https://stackoverflow.com/questions/30126671/understanding-the-error-syntaxerror-expected-expression-got
- 7: https://stackoverflow.com/questions/31308495/syntaxerror-expected-expression-got-while-running-angularjs-and-node
- 8: https://stackoverflow.com/questions/49434990/syntaxerror-expected-expression-got-different-results-on-different-envir
🌐 Web query:
Chrome SyntaxError Unexpected token '<' when HTML served as script
💡 Result:
The error Uncaught SyntaxError: Unexpected token '<' occurs when the browser expects a JavaScript file but receives an HTML document instead [1][2][3]. Because the browser attempts to parse the content as JavaScript, it encounters the '<' character—typically the start of an HTML tag like or —and fails immediately [1][4][5]. This issue most commonly arises from server-side misconfiguration rather than a syntax error in your code [2]. Common causes include: 1. Incorrect File Paths: The browser is requesting a JavaScript file (e.g., /js/app.js), but the server cannot find it at that location. If your server is configured to serve your main HTML file for all non-existent paths (common in Single Page Applications or specific routing setups), it will return the HTML content instead of the expected script [1][6][2]. 2. Server Routing Misconfiguration: Your web server may be configured to return index.html for all requests, regardless of the requested path. When the browser requests your scripts or CSS, the server sends the HTML file back, causing the parser to crash [7][4][2]. 3. Redirecting 404 Errors: If your server is configured to redirect 404 "Not Found" errors to the homepage, it will send your index.html page whenever a script path is invalid, again causing the same syntax error [2][5]. How to Debug and Fix: 1. Check the Network Tab: Open your browser's Developer Tools (F12 or Right-click > Inspect), navigate to the Network tab, and refresh the page [8]. Look for the JavaScript file that triggered the error [1][2]. 2. Inspect the Response: Click on the failing JavaScript request to view its Response. If you see HTML code (like a doctype declaration or tag), your server is serving the wrong content [9][4][8]. 3. Fix the Path or Server Logic: - Ensure your script src attributes in HTML are correct and pointing to the right directory (e.g., using absolute paths starting with /) [3]. - Verify that your server configuration (e.g., Express, Nginx, Apache) is correctly serving static assets and not catching those requests in a catch-all route [1][6]. - If using a router, ensure it only serves the HTML file for routes that are intended to be application views, not for file paths representing static assets [6][9].
Citations:
- 1: https://stackoverflow.com/questions/67654711/uncaught-syntaxerror-unexpected-token-express-typescript
- 2: https://stackoverflow.com/questions/3630006/error-uncaught-syntaxerror-unexpected-token
- 3: https://stackoverflow.com/questions/55616670/how-to-fix-uncaught-syntaxerror-unexpected-token
- 4: https://stackoverflow.com/questions/55475905/unexpected-token-javascript-files-being-rendered-as-html
- 5: https://stackoverflow.com/questions/12205171/syntax-error-unexpected-token-in-web-console
- 6: https://stackoverflow.com/questions/58090054/express-and-webpack-problem-uncaught-syntaxerror-unexpected-token
- 7: Uncaught SyntaxError: Unexpected token < react/create-react-app#4718
- 8: https://stackoverflow.com/questions/32637559/how-to-debug-unexpected-token-in-chrome-console
- 9: https://stackoverflow.com/questions/38221451/chrome-complaining-about-html-tags-in-app-js
Broaden the stale-chunk SyntaxError fallback for non-V8 browsers
isHtmlParsedAsScriptError only catches Unexpected token '<', so Firefox’s equivalent failure (SyntaxError: expected expression, got '<') won’t trigger the safety-net reload. Include the browser’s characteristic wording or another reliable guard alongside the filename pattern.
🤖 Prompt for 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.
In `@src/utils/lazy-with-reload.js` around lines 40 - 55, Update
isHtmlParsedAsScriptError to recognize Firefox’s SyntaxError wording, “expected
expression, got '<',” in addition to the existing “Unexpected token '<'” check.
Preserve the existing SyntaxError detection and filename pattern guard, while
allowing either characteristic message to trigger the stale-chunk fallback.
| // Fingerprints the statically-loaded <script> tags present the first time | ||
| // this module runs on a given page load - i.e. before any lazy chunk has | ||
| // been requested. This identifies "which build is currently running" | ||
| // without requiring the consuming app to expose a dedicated build-version | ||
| // global. Computed once and cached: document.scripts grows over time as | ||
| // webpack's runtime appends a <script> tag for every lazy chunk that loads, | ||
| // so reading it lazily-but-uncached would make the fingerprint drift within | ||
| // a single build, not just across a real deploy. | ||
| let cachedBuildFingerprint; | ||
| const getBuildFingerprint = () => { | ||
| if (cachedBuildFingerprint === undefined) { | ||
| cachedBuildFingerprint = | ||
| typeof document !== "undefined" | ||
| ? Array.from(document.scripts) | ||
| .map((s) => s.src) | ||
| .filter(Boolean) | ||
| .sort() | ||
| .join(",") | ||
| : ""; | ||
| } | ||
| return cachedBuildFingerprint; | ||
| }; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate file =="
git ls-files | rg '(^|/)lazy-with-reload\.js$|package\.json$|webpack|vite|entry' || true
echo "== file outline =="
ast-grep outline src/utils/lazy-with-reload.js --view compact || true
echo "== relevant source =="
cat -n src/utils/lazy-with-reload.js
echo "== search usages =="
rg -n "lazy-with-reload|reloadOnChunkError|entry:|main:|webpack|lazyWithReload|reload" -S . --glob '!node_modules' --glob '!dist' --glob '!build' | head -200Repository: OpenStackweb/openstack-uicore-foundation
Length of output: 25127
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== webpack common entry/snippet =="
cat -n webpack.common.js | sed -n '1,80p'
echo "== tests around fingerprint/session and script mocks =="
cat -n src/utils/__tests__/lazy-with-reload.test.js | sed -n '1,220p'
echo "== read-only model of the fingerprint/current-state race =="
node - <<'JS'
function initialState(scripts) {
return { cachedBuildFingerprint: undefined, scripts };
}
function getBuildFingerprint(state) {
if (state.cachedBuildFingerprint === undefined) {
state.cachedBuildFingerprint = Array.from(state.scripts)
.map(s => s.src)
.filter(Boolean)
.sort()
.join(",");
}
return state.cachedBuildFingerprint;
}
function reloadOnChunkErrorFirst(state) {
const currentBuild = getBuildFingerprint(state);
return { rebuildNow: false, savedBuild: currentBuild };
}
function simulatePostReload(state, additionalScriptsLoadedBeforeNextFailure) {
state.scripts.push(...additionalScriptsLoadedBeforeNextFailure.map(src => ({ src })));
state.cachedBuildFingerprint = undefined;
}
function reloadOnChunkErrorNext(state) {
const currentBuild = getBuildFingerprint(state);
const storedBuilds = [state.cachedBuildFingerprint];
return { rebuildNow: true, savedBuild: currentBuild, storedBuilds };
}
const initial = initialState([{ src: "main.js" }]);
const first = reloadOnChunkErrorFirst(initial);
simulatePostReload(initial, [{ src: "lazy1.js" }]);
const second = reloadOnChunkErrorNext(initial);
console.log({
firstFingerprint: first.savedBuild,
reloadStateBuildStored: first.savedBuild,
secondFingerprint: second.savedBuild,
fingerprintsDiffer: first.savedBuild !== second.savedBuild,
});
JSRepository: OpenStackweb/openstack-uicore-foundation
Length of output: 17308
Compute the build fingerprint at bootstrap instead of lazily on the first chunk error.
getBuildFingerprint() is first called inside reloadOnChunkError, after any lazy chunks that happened to load successfully in this session may have already been appended to document.scripts. Since the guard stores the fingerprint seen at that first failure, the post-reload fingerprint can include a different set of loaded chunks and bypass the once-per-build throttle.
♻️ Suggested fix: compute the fingerprint eagerly at module evaluation time
-let cachedBuildFingerprint;
-const getBuildFingerprint = () => {
- if (cachedBuildFingerprint === undefined) {
- cachedBuildFingerprint =
- typeof document !== "undefined"
- ? Array.from(document.scripts)
- .map((s) => s.src)
- .filter(Boolean)
- .sort()
- .join(",")
- : "";
- }
- return cachedBuildFingerprint;
-};
+const cachedBuildFingerprint =
+ typeof document !== "undefined"
+ ? Array.from(document.scripts)
+ .map((s) => s.src)
+ .filter(Boolean)
+ .sort()
+ .join(",")
+ : "";
+const getBuildFingerprint = () => cachedBuildFingerprint;This still relies on this module being evaluated before app-level lazy chunk imports are attempted, which needs to hold since it is bundled as its own webpack entry.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Fingerprints the statically-loaded <script> tags present the first time | |
| // this module runs on a given page load - i.e. before any lazy chunk has | |
| // been requested. This identifies "which build is currently running" | |
| // without requiring the consuming app to expose a dedicated build-version | |
| // global. Computed once and cached: document.scripts grows over time as | |
| // webpack's runtime appends a <script> tag for every lazy chunk that loads, | |
| // so reading it lazily-but-uncached would make the fingerprint drift within | |
| // a single build, not just across a real deploy. | |
| let cachedBuildFingerprint; | |
| const getBuildFingerprint = () => { | |
| if (cachedBuildFingerprint === undefined) { | |
| cachedBuildFingerprint = | |
| typeof document !== "undefined" | |
| ? Array.from(document.scripts) | |
| .map((s) => s.src) | |
| .filter(Boolean) | |
| .sort() | |
| .join(",") | |
| : ""; | |
| } | |
| return cachedBuildFingerprint; | |
| }; | |
| // Fingerprints the statically-loaded <script> tags present the first time | |
| // this module runs on a given page load - i.e. before any lazy chunk has | |
| // been requested. This identifies "which build is currently running" | |
| // without requiring the consuming app to expose a dedicated build-version | |
| // global. Computed once and cached: document.scripts grows over time as | |
| // webpack's runtime appends a <script> tag for every lazy chunk that loads, | |
| // so reading it lazily-but-uncached would make the fingerprint drift within | |
| // a single build, not just across a real deploy. | |
| const cachedBuildFingerprint = | |
| typeof document !== "undefined" | |
| ? Array.from(document.scripts) | |
| .map((s) => s.src) | |
| .filter(Boolean) | |
| .sort() | |
| .join(",") | |
| : ""; | |
| const getBuildFingerprint = () => cachedBuildFingerprint; |
🤖 Prompt for 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.
In `@src/utils/lazy-with-reload.js` around lines 61 - 82, Compute and cache the
build fingerprint eagerly during module evaluation, before any lazy chunks can
load, instead of initializing cachedBuildFingerprint inside getBuildFingerprint.
Keep getBuildFingerprint as a read-only accessor and preserve the existing
document-scripts fingerprinting and non-browser fallback behavior.
| export const reloadOnChunkError = (error, filename, chunkFilenamePattern) => { | ||
| if (!isChunkLoadError(error, filename, chunkFilenamePattern)) return false; | ||
|
|
||
| const currentBuild = getBuildFingerprint(); | ||
| const state = readReloadState(); | ||
|
|
||
| if (state && state.build === currentBuild) { | ||
| reportRecoveryFailed(error, filename); | ||
| return false; | ||
| } | ||
|
|
||
| writeReloadState({ build: currentBuild }); | ||
| try { | ||
| window.sessionStorage.setItem(PENDING_CONFIRMATION_KEY, "1"); | ||
| } catch { | ||
| // ignore - see readReloadState/writeReloadState | ||
| } | ||
| window.location.reload(); | ||
| return true; | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Concurrent chunk failures on first occurrence can trigger a false "persisted after auto-reload" report.
reloadOnChunkError writes RELOAD_STATE_KEY synchronously (Line 135) before the actual navigation from window.location.reload() takes effect. If two lazy chunks fail around the same tick (e.g., two separate route-level lazyWithReload imports both hitting the same stale build), the first call writes state and reloads; the second call reads back the state just written, sees state.build === currentBuild, and reports via reportRecoveryFailed as if the reload already happened and failed to fix things — even though no reload has completed yet. This produces a spurious Sentry alert on every multi-chunk-failure page load, independent of whether recovery actually works.
♻️ Suggested fix: guard with an in-memory "reload already triggered this tick" flag
+let reloadTriggeredThisPage = false;
+
export const reloadOnChunkError = (error, filename, chunkFilenamePattern) => {
if (!isChunkLoadError(error, filename, chunkFilenamePattern)) return false;
+ if (reloadTriggeredThisPage) return true; // reload already in flight for this page load
+
const currentBuild = getBuildFingerprint();
const state = readReloadState();
if (state && state.build === currentBuild) {
reportRecoveryFailed(error, filename);
return false;
}
+ reloadTriggeredThisPage = true;
writeReloadState({ build: currentBuild });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const reloadOnChunkError = (error, filename, chunkFilenamePattern) => { | |
| if (!isChunkLoadError(error, filename, chunkFilenamePattern)) return false; | |
| const currentBuild = getBuildFingerprint(); | |
| const state = readReloadState(); | |
| if (state && state.build === currentBuild) { | |
| reportRecoveryFailed(error, filename); | |
| return false; | |
| } | |
| writeReloadState({ build: currentBuild }); | |
| try { | |
| window.sessionStorage.setItem(PENDING_CONFIRMATION_KEY, "1"); | |
| } catch { | |
| // ignore - see readReloadState/writeReloadState | |
| } | |
| window.location.reload(); | |
| return true; | |
| }; | |
| let reloadTriggeredThisPage = false; | |
| export const reloadOnChunkError = (error, filename, chunkFilenamePattern) => { | |
| if (!isChunkLoadError(error, filename, chunkFilenamePattern)) return false; | |
| if (reloadTriggeredThisPage) return true; // reload already in flight for this page load | |
| const currentBuild = getBuildFingerprint(); | |
| const state = readReloadState(); | |
| if (state && state.build === currentBuild) { | |
| reportRecoveryFailed(error, filename); | |
| return false; | |
| } | |
| reloadTriggeredThisPage = true; | |
| writeReloadState({ build: currentBuild }); | |
| try { | |
| window.sessionStorage.setItem(PENDING_CONFIRMATION_KEY, "1"); | |
| } catch { | |
| // ignore - see readReloadState/writeReloadState | |
| } | |
| window.location.reload(); | |
| return true; | |
| }; |
🤖 Prompt for 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.
In `@src/utils/lazy-with-reload.js` around lines 124 - 143, Update
reloadOnChunkError to track, in memory, whether a reload has already been
triggered during the current page lifecycle or tick before consulting persisted
reload state. Have subsequent concurrent chunk failures return without calling
reportRecoveryFailed, while preserving the existing persisted-state check for
failures occurring after navigation and the current write/sessionStorage/reload
flow for the first failure.
| // Sentry beforeSend hook: drops chunk-load-error events from being reported, | ||
| // since a first-time occurrence is expected to self-heal via the reload | ||
| // above. A repeat failure (reload didn't help) is reported separately and | ||
| // explicitly via reportRecoveryFailed's Sentry.captureMessage call, which is | ||
| // a message-type event (no .exception), so it is unaffected by this filter. | ||
| export const chunkErrorSentryBeforeSend = (event) => { | ||
| const exceptionValues = event.exception?.values || []; | ||
| const matchesChunkError = exceptionValues.some((exceptionValue) => | ||
| isChunkLoadError({ | ||
| name: exceptionValue.type, | ||
| message: exceptionValue.value | ||
| }) | ||
| ); | ||
| return matchesChunkError ? null : event; | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Sentry filter drops the filename cross-check the design explicitly calls for, over-broadening the match.
The header comment (Lines 30-37) stresses cross-checking the filename against chunkFilenamePattern so the HTML-as-script SyntaxError match "can't false-match an unrelated SyntaxError elsewhere in the app." But here isChunkLoadError is called with only {name, message} — no filename — so isHtmlParsedAsScriptError's !filename || ... check always short-circuits to true, and any SyntaxError with the message "Unexpected token '<'" gets silently dropped from Sentry, regardless of source. That message is a very common, generic symptom (e.g. HTML returned by a misconfigured API/proxy, auth redirect, etc.), so this filter risks masking unrelated production issues from monitoring.
Sentry exception values include stack frames that typically carry a filename; consider extracting the top frame's filename for the cross-check:
export const chunkErrorSentryBeforeSend = (event) => {
const exceptionValues = event.exception?.values || [];
- const matchesChunkError = exceptionValues.some((exceptionValue) =>
- isChunkLoadError({
- name: exceptionValue.type,
- message: exceptionValue.value
- })
- );
+ const matchesChunkError = exceptionValues.some((exceptionValue) => {
+ const frames = exceptionValue.stacktrace?.frames || [];
+ const culpritFilename = frames[frames.length - 1]?.filename;
+ return isChunkLoadError(
+ { name: exceptionValue.type, message: exceptionValue.value },
+ culpritFilename
+ );
+ });
return matchesChunkError ? null : event;
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Sentry beforeSend hook: drops chunk-load-error events from being reported, | |
| // since a first-time occurrence is expected to self-heal via the reload | |
| // above. A repeat failure (reload didn't help) is reported separately and | |
| // explicitly via reportRecoveryFailed's Sentry.captureMessage call, which is | |
| // a message-type event (no .exception), so it is unaffected by this filter. | |
| export const chunkErrorSentryBeforeSend = (event) => { | |
| const exceptionValues = event.exception?.values || []; | |
| const matchesChunkError = exceptionValues.some((exceptionValue) => | |
| isChunkLoadError({ | |
| name: exceptionValue.type, | |
| message: exceptionValue.value | |
| }) | |
| ); | |
| return matchesChunkError ? null : event; | |
| }; | |
| // Sentry beforeSend hook: drops chunk-load-error events from being reported, | |
| // since a first-time occurrence is expected to self-heal via the reload | |
| // above. A repeat failure (reload didn't help) is reported separately and | |
| // explicitly via reportRecoveryFailed's Sentry.captureMessage call, which is | |
| // a message-type event (no .exception), so it is unaffected by this filter. | |
| export const chunkErrorSentryBeforeSend = (event) => { | |
| const exceptionValues = event.exception?.values || []; | |
| const matchesChunkError = exceptionValues.some((exceptionValue) => { | |
| const frames = exceptionValue.stacktrace?.frames || []; | |
| const culpritFilename = frames[frames.length - 1]?.filename; | |
| return isChunkLoadError( | |
| { name: exceptionValue.type, message: exceptionValue.value }, | |
| culpritFilename | |
| ); | |
| }); | |
| return matchesChunkError ? null : event; | |
| }; |
🤖 Prompt for 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.
In `@src/utils/lazy-with-reload.js` around lines 210 - 224, Update
chunkErrorSentryBeforeSend to extract the relevant filename from each Sentry
exception’s stack frames and pass it with the exception type and value to
isChunkLoadError. Preserve the existing filtering behavior for genuine
chunk-load errors while ensuring the HTML-as-script SyntaxError path requires a
filename matching chunkFilenamePattern.
https://app.clickup.com/t/9014802374/86bb1gp6z
Summary by CodeRabbit
New Features
Tests
Chores
5.0.45-beta.0.