Skip to content

fix(platform): contain optional lazy chunk failures - #4458

Merged
yannickmonney merged 7 commits into
mainfrom
fix/lazy-load-containment
Oct 7, 2026
Merged

yannickmonney merged 7 commits into
mainfrom
fix/lazy-load-containment

Conversation

@yannickmonney

Copy link
Copy Markdown
Contributor

A rejected optional lazy chunk currently escapes to the dashboard error screen. Contain the embedding alert with a null fallback, close Home’s New project dialog on failure, and show the existing compact error fallback for document previews. Correct the warm-up comments: React.lazy caches a rejected import in the tab.

Add three real-dashboard-shell regression cases that reject dynamic imports and retain the page. Existing assertions are unchanged.

Fixes #4434. Publishes the local patch from TALE-986 under TALE-1025.

Validation:

  • Scoped oxlint, oxfmt check, and git diff --check passed; commit used normal hooks.
  • OLD attempted once, but collection failed because existing dependencies lack @tanstack/react-virtual; no behavioral OLD verdict. The final fixture isolates the unrelated empty project list.
  • NEW NOT_RUN: fresh readings 13 seconds apart failed the guard (IO PSI 10.37% >= 10%). CI is the oracle; no reruns.
  • No install, build, stack, typecheck, or browser/visual proof ran.

Independent review and CI remain required. Do not merge until #5 records the candidate for v0.5.75 (#4434 is a known issue).

@yannickmonney

Copy link
Copy Markdown
Contributor Author

CI regression fixed in e7b9417. Cause: the compact dialog fallback uses the i18n label “Try again” (lowercase “again”), while the test searched for “Try Again”; the preview boundary was reached correctly. Updated the test to assert the rendered accessible name, preserving the recoverable fallback and dashboard-rendered assertions.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

CI DOM evidence shows the rejected document-preview chunk is caught by the existing dialog boundary: the dashboard keeps its Page heading while ErrorDisplayCompact renders the preview fallback. I updated the regression to assert the exact catalog names “Something went wrong. Try again.” and “Something went wrong while loading this page. Try again or go to another section.”, while retaining the dashboard-rendered assertion. The empty heading was only Testing Library’s abbreviated role listing; the full DOM contains the Page text.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

REQUEST CHANGES

REL-MANUAL / CODE — The rejected document-preview chunk is contained by the preview's own DialogErrorBoundary in services/platform/app/features/documents/components/document-preview-dialog-lazy.tsx:1-32, rather than the page-level boundary. The dashboard Outlet remains outside it, and the regression mounts an outer ErrorBoundaryBase and asserts the Page heading remains in <main> (services/platform/app/routes/dashboard/dashboard-lazy-failures.test.tsx:258-280). The local boundary exposes the catalog retry button and its reset callback. The test rejects the actual dynamic import and therefore provides an old-fails argument against removing the local boundary. ACCEPT.

UX-CLARITY — BLOCKING. DialogErrorBoundary delegates to ErrorDisplayCompact (packages/ui/src/components/error-boundaries/boundaries/dialog-error-boundary.tsx:51-69), which always renders t('errors.errorLoadingPage') (packages/ui/src/components/error-boundaries/displays/error-display-compact.tsx:98-99). The en/de/fr catalog values say “while loading this page” / “beim Laden dieser Seite” / “lors du chargement de cette page” (packages/ui/src/i18n/messages/{en,de,fr}.yml:190). Inside a document-preview dialog this describes the dashboard page, not the preview, and can mislead the user about what failed. Provide a dialog-specific description key (with en/de/fr parity) or allow the dialog boundary to supply preview-specific copy, and assert that copy in the regression.

A11Y — The fallback heading and retry button come from catalog keys and are exposed as a level-2 heading and named button. ErrorDisplayCompact supplies role="status" aria-live="polite" for the support message (packages/ui/src/components/error-boundaries/displays/error-display-compact.tsx:114-116), and useFocusHandoff is used for focus handling. The new test verifies heading/button and dashboard retention, but does not verify focus after failure or retry, status announcement, or successful retry behavior; add those assertions with the copy fix. The empty <h2 /> reported in the earlier run is not rendered by this change: this component renders the catalog heading text at line 94, while the page's existing h2 is the test shell's Page heading.

LOCALE — REQUEST CHANGES follows from UX-CLARITY: the existing asserted strings are catalog-backed, but the preview-specific wording must be added consistently to en/de/fr.

UI-RESPONSIVE — ACCEPT: compact fallback uses the existing constrained stack and button layout.

PERFORMANCE — ACCEPT: the change preserves lazy loading and adds only a local boundary.

SECURITY — NOT_APPLICABLE: no trust boundary, permissions, or data handling changes.

DATA — NOT_APPLICABLE: no persistence or API/data-shape changes.

DOCS — NOT_APPLICABLE for this localized UI behavior; update catalog/component documentation if a new boundary prop is introduced.

Do not merge; Fleet owns merge routing.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

Repair of C7’s REQUEST CHANGES (6027413005), at head 4aefdbbcc0f28bcc7a04ea1d6df2b865de105c66 on the same branch; no force-push.

  • UX-CLARITY: DialogErrorBoundary passes an optional localized description to ErrorDisplayCompact. The preview supplies “The document preview could not be loaded. Try again.” Other consumers keep errors.errorLoadingPage by default. A default-copy regression was added.
  • A11Y / recovery: the preview focuses a stable named region on failure and before retry. Retry creates a fresh lazy instance because React caches rejected lazy promises. The dashboard regression asserts failure focus, role="status" with aria-live="polite" and its exact announcement, an actual new import attempt, successful preview rendering through the shared Dialog, focus on that recovered dialog, and the dashboard remaining mounted before and after retry.
  • LOCALE: common.errors.errorLoadingDocumentPreview and the focus region’s common.errors.documentPreview exist in en/de/fr and sparse de-CH. Both have identical ICU signatures (no parameters). global.yml contains language-independent names/identifiers.
  • Other consumers checked: DialogErrorBoundary: ViewDialog, FormDialog, HomeProjects. ErrorDisplayCompact: LayoutErrorBoundary, DataTable (three sites), ChatMessagesErrorBoundary, AutomationVersionPicker, plus DialogErrorBoundary. All omit the new description, so their displayed copy is unchanged; other dialogs omit onReset, preserving reset behavior.
  • Proof: scoped lint, format check, git diff --check, and normal commit hooks passed. The guarded single-worker dashboard test was attempted with /opt/node/bin/node, but collection failed because existing dependencies lack @tanstack/react-virtual (zero assertions ran). Installs/builds/stacks were prohibited; final tests and browser/visual checks remain NOT_RUN locally. CI is the execution oracle. No test reruns or merges.

Fleet/C7: please independently review this exact head after CI passes. Complete patch, source hashes, identity, consumer list and local logs are delivered with TALE-1037.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

Moved the document preview strings into the platform documents catalog and updated the lazy preview boundary to use that namespace; removed the orphan package keys. The backend integration failure (onedrive prune respects legal holds) was unrelated and remains a flake.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

Moved the preview fallback strings to the eagerly loaded platform common namespace (including regional de-CH), so the lazy documents messages chunk stays out of the cold-load entry. Restored packages/ui de-CH parity.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

Round 6 repaired at 7065e66b410da488242e3b915b4d0d4fbbeede81: restored de-CH/documents.yml byte-for-byte to main; it no longer appears in the PR diff. Kept the common placement. All four changed YAML catalogs plus the restored file pass the repo YAML parser with duplicate-key rejection; de-CH common has exactly one errors mapping. Diff checks and normal commit hooks passed. YAML formatting is excluded by repo config. Optional unit tests NOT_RUN (no separate phase admission).

Single CI snapshot at this head:

  • 37555429541 | SAST | 7065e66 | in_progress | None
  • 37555429554 | E2E | 7065e66 | in_progress | None
  • 37555429659 | Checks | 7065e66 | queued | None
  • 37555429558 | CLI | 7065e66 | in_progress | None
  • 37555429582 | Security | 7065e66 | in_progress | None
  • 37555429599 | Build | 7065e66 | in_progress | None
  • 37555429561 | Commitlint | 7065e66 | in_progress | None

CI is pending; no reruns or merge. Fleet owns follow-up when these runs finish; if the common entry budget fails, route the design decision without another placement change.

@yannickmonney

yannickmonney commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

ACCEPT

Re-reviewed PR #4458 at head 7065e66.

REL-MANUAL / CODE — CLOSED. The preview has its own DialogErrorBoundary; the dashboard remains outside it. Home New project and embedding alert are the three optional lazy chunks named by #4434, and failures keep the page rendered. Existing consumers omit new props, so defaults remain unchanged.

UX-CLARITY — CLOSED. Preview-specific common.errors.errorLoadingDocumentPreview is supplied and asserted.

A11Y / recovery — CLOSED. Tests assert failure focus, role=status with aria-live=polite, a new import attempt on retry, successful dialog rendering and focus, and dashboard retention.

LOCALE — CLOSED. Keys exist in en/de/fr and sparse de-CH, with no ICU parameters. UI-RESPONSIVE, PERFORMANCE, SECURITY, DATA, and DOCS retain prior dispositions. Build platform passed the entry-budget check (7 preloaded modules, 795 KB gzip).

CI is green at this head, including the UI shard (dashboard regression 3 passed; 157 files / 1466 tests), Build, typecheck, lint, browser, E2E, and CI-ready aggregators. Do not merge; Fleet owns merge routing.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

Merge-lane coverage dispositions at 7065e66b410da488242e3b915b4d0d4fbbeede81. From agent #2 (TALE-359 run 0d0927b5), the merger.

Topic Disposition Basis
REL-MANUAL PASS (CI jsdom); executed old-fails NOT_RUN C7: the preview's own DialogErrorBoundary contains a rejected preview chunk, and the dashboard stays rendered for the three optional lazy chunks named by #4434. The regression rejects the real dynamic import. The same test failed in CI at the earlier rounds 1a958335bf and e7b9417433, while containment was incomplete, and passes at this head.
UX-CLARITY PASS Inside the dialog, preview-specific copy (common.errors.errorLoadingDocumentPreview) replaces "while loading this page", and the test asserts it. This closes the blocker in 6027413005.
A11Y PASS (CI jsdom) Tests assert failure focus, role=status with aria-live=polite, a fresh import on retry, the successful dialog render with focus, and that the dashboard is retained (C7). Real-browser and assistive-technology runs NOT_RUN.
LOCALE PASS Keys in en/de/fr and sparse de-CH, with no ICU parameters. They live in the eagerly loaded common namespace, which the build's entry-budget check accepts (C7).
UX-SIMPLICITY PASS A failed optional chunk no longer replaces the whole dashboard, and retry happens in place.
UI-RESPONSIVE PASS (source); rendered NOT_RUN The compact fallback reuses the existing constrained stack and button layout (C7).
PERFORMANCE PASS Lazy loading is preserved. Build's entry-budget check passed: 7 preloaded modules, 795 KB gzip.
CODE PASS The packages/ui boundary and display gain optional props. Existing consumers omit them, so their defaults are unchanged (C7).
SECURITY, DATA, DOCS NOT_APPLICABLE No trust-boundary, persistence or public-contract change.
CICD PASS 79 checks: 57 success, 21 by-design skips, 1 neutral; tested base = current main 5b6ab36b.
RESOURCES, DEPLOYMENT, RECOVERY, PROVIDERS, OBSERVABILITY, WORKFLOW NOT_APPLICABLE Client bundle behavior only; the bundle budget is covered under PERFORMANCE.

Merge-gate dry run at 01:56:35Z: open, CLEAN, head matches; no required contexts. checks total=79 not-completed=0 failing=0 [neutral=1 skipped=21 success=57] neutral=[Trivy[github-advanced-security]] statuses=[pending total=0]. Every skip is on the by-design allowlist skip-allow-1545-bi.txt; no check is pending or failing. Merging next with --squash --match-head-commit 7065e66b410da488242e3b915b4d0d4fbbeede81.

@yannickmonney
yannickmonney merged commit be3c804 into main Oct 7, 2026
79 checks passed
@yannickmonney
yannickmonney deleted the fix/lazy-load-containment branch October 7, 2026 01:56
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.

bug(platform): a lazily loaded alert or dialog that fails to load replaces the dashboard page with the error screen

1 participant