diff --git a/src/renderer/src/lib/lazy-chunk-error-classification.ts b/src/renderer/src/lib/lazy-chunk-error-classification.ts index 90340a56e50..54d93851351 100644 --- a/src/renderer/src/lib/lazy-chunk-error-classification.ts +++ b/src/renderer/src/lib/lazy-chunk-error-classification.ts @@ -49,6 +49,8 @@ function classifyErrorMessage(message: string): string { const normalized = message.toLowerCase() const looksLikeJsonParseFailure = normalized.includes('json') || normalized.includes('not valid json') + // Why: recovery should catch broken emitted JS chunks without treating + // ordinary data-parse failures as app-shell corruption. if ( (!looksLikeJsonParseFailure && (normalized.includes('unexpected token') || @@ -59,6 +61,8 @@ function classifyErrorMessage(message: string): string { ) { return 'syntax' } + // Why: browsers report dynamic import failures differently, but these all + // indicate a missing/stale chunk that a guarded reload may repair. if ( normalized.includes('failed to fetch dynamically imported module') || normalized.includes('error loading dynamically imported module') || @@ -77,6 +81,8 @@ function classifyErrorCategory(messageClass: string, errorName: string): string if (messageClass === 'syntax') { return 'syntax' } + // Why: webpack-style chunk failures can arrive as a name without a useful + // message, so keep the name as a narrow fetch fallback. if (messageClass === 'fetch' || errorName === 'ChunkLoadError') { return 'fetch' } diff --git a/tests/e2e/renderer-recovery-toast.spec.ts b/tests/e2e/renderer-recovery-toast.spec.ts index d91306bba30..922f655d471 100644 --- a/tests/e2e/renderer-recovery-toast.spec.ts +++ b/tests/e2e/renderer-recovery-toast.spec.ts @@ -78,20 +78,26 @@ test('explains guarded renderer recovery once after reload or restart markers', ) .toBeNull() - await orcaPage.evaluate(async () => { - await window.api.settings.set({ uiLanguage: 'es' }) - }) - await seedRecoveryMarker(orcaPage, 'session', 'lazy-chunk-reload') - await orcaPage.reload() - await waitForRendererBoot(orcaPage) + try { + await orcaPage.evaluate(async () => { + await window.api.settings.set({ uiLanguage: 'es' }) + }) + await seedRecoveryMarker(orcaPage, 'session', 'lazy-chunk-reload') + await orcaPage.reload() + await waitForRendererBoot(orcaPage) - await expect(orcaPage.getByText('Orca se recargó para recuperarse')).toBeVisible() - await expect( - orcaPage.getByText('Se recuperó de un error de carga recargando la interfaz de la app.') - ).toBeVisible() - await expect - .poll(() => - orcaPage.evaluate((key) => window.sessionStorage.getItem(key), SESSION_NOTIFICATION_KEY) - ) - .toBeNull() + await expect(orcaPage.getByText('Orca se recargó para recuperarse')).toBeVisible() + await expect( + orcaPage.getByText('Se recuperó de un error de carga recargando la interfaz de la app.') + ).toBeVisible() + await expect + .poll(() => + orcaPage.evaluate((key) => window.sessionStorage.getItem(key), SESSION_NOTIFICATION_KEY) + ) + .toBeNull() + } finally { + await orcaPage.evaluate(async () => { + await window.api.settings.set({ uiLanguage: 'en' }) + }) + } })