[CSM Portal Microapp]: app-wide crash isolation and a root error boundary - #1377
Conversation
extractIixAttachmentIds had no upper bound and deduped via an O(n) ids.includes() scan per match. useResolvedInlineImageHtml fires one parallel authenticated Blob fetch per id it returns, so a comment/description with an unreasonable number of distinct .iix images would fire an unbounded number of concurrent fetches. Caps collection at 20 unique ids (via a Set, also fixing the O(n) scan) — ids past the cap are simply never extracted, so they fall through existing "unresolved reference" handling in replaceInlineImageSrcs (stripped, not left pointing at an auth-gated URL).
No boundary existed above the page level anywhere in the app — App.tsx, main.tsx, and MainLayout.tsx all had none, and several pages (AnnouncementsPage, HomePage, MorePage, ...) have no boundary of their own either. An uncaught render error in any of those unmounted the entire React tree to a blank white screen with no way back short of force-quitting the WebView. This is almost certainly what the Announcements "white space" bug actually was: a render-time throw (the createdBy UserReference crash) with nothing above it to catch it. Mirrors the webapp's AppErrorBoundary, trimmed to this app's simpler recovery options — no clipboard/correlation-ID reporting, just a themed "Something went wrong / Reload" screen, logged via the existing Logger.error.
Four lists render backend-shaped data (UserReference createdBy, attachment type, ...) one item per iteration, all under a single list-level ErrorBoundary: CaseActivityFeed (comments/lifecycle entries/attachments merged together), AttachmentsTab's row list, SupportPage's case list, AnnouncementsPage's announcement list. A render error in any one item was caught by that shared boundary, which unmounts everything below it — not just the offending item, every sibling too. This is exactly how one attachment with a bad createdBy value took down the entire comments feed alongside it. ListItemErrorBoundary wraps a single item so a render error there degrades to a small inline "Couldn't display this item" placeholder instead, leaving every other item in the list unaffected. No built-in retry: a render error here is a code/data-shape bug, not a transient failure a tap can fix, consistent with how every other ErrorBoundary in this app already behaves.
📝 WalkthroughWalkthroughThe microapp adds application-level and list-item error boundaries. It isolates failures in case, announcement, support, and activity-feed items. It also recognizes image HTML and caps unique inline image extraction at 20 IDs. ChangesMicroapp error handling
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant main.tsx
participant AppErrorBoundary
participant ListItemErrorBoundary
participant CaseActivityFeed
main.tsx->>AppErrorBoundary: render App
AppErrorBoundary->>CaseActivityFeed: render application content
CaseActivityFeed->>ListItemErrorBoundary: render each feed item
ListItemErrorBoundary-->>CaseActivityFeed: render item fallback on failure
AppErrorBoundary-->>main.tsx: render recovery screen on root failure
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 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.
🧹 Nitpick comments (1)
apps/csm-portal/microapp/src/components/common/AppErrorBoundary.tsx (1)
43-55: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd regression tests for the microapp error-boundary scopes.
The microapp package has only build/lint scripts, and there are no
test/specfiles underapps/csm-portal/microapp. Add component tests for these new boundary behaviors:
- Root fallback and reload action for
AppErrorBoundary.tsx.- Item isolation with one failing child and healthy siblings for
ListItemErrorBoundary.tsx.🤖 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 `@apps/csm-portal/microapp/src/components/common/AppErrorBoundary.tsx` around lines 43 - 55, Add regression component tests for the microapp error-boundary scopes: in apps/csm-portal/microapp/src/components/common/AppErrorBoundary.tsx (lines 43-55), verify the root fallback renders and its reload action works; in apps/csm-portal/microapp/src/components/common/ListItemErrorBoundary.tsx (lines 44-67), verify one failing child is isolated while healthy siblings remain rendered. Add the necessary test setup and scripts without changing the boundary implementations.
🤖 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.
Nitpick comments:
In `@apps/csm-portal/microapp/src/components/common/AppErrorBoundary.tsx`:
- Around line 43-55: Add regression component tests for the microapp
error-boundary scopes: in
apps/csm-portal/microapp/src/components/common/AppErrorBoundary.tsx (lines
43-55), verify the root fallback renders and its reload action works; in
apps/csm-portal/microapp/src/components/common/ListItemErrorBoundary.tsx (lines
44-67), verify one failing child is isolated while healthy siblings remain
rendered. Add the necessary test setup and scripts without changing the boundary
implementations.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 20c58184-2499-4557-91a6-5af1c18f7454
📒 Files selected for processing (10)
apps/csm-portal/microapp/src/components/case-detail/AttachmentsTab.tsxapps/csm-portal/microapp/src/components/case-detail/CaseActivityFeed.tsxapps/csm-portal/microapp/src/components/case-detail/CommentBody.tsxapps/csm-portal/microapp/src/components/common/AppErrorBoundary.tsxapps/csm-portal/microapp/src/components/common/ListItemErrorBoundary.tsxapps/csm-portal/microapp/src/main.tsxapps/csm-portal/microapp/src/pages/AnnouncementsPage.tsxapps/csm-portal/microapp/src/pages/SupportPage.tsxapps/csm-portal/microapp/src/pages/UpdatesPage.tsxapps/csm-portal/microapp/src/utils/inlineImages.ts
Summary
Two gaps found while auditing this app's error-boundary coverage (webapp checked for reference — its
AppErrorBoundarycovers the root-level gap the same way, but has no per-item isolation either, so that part is new here):App.tsx,main.tsx,MainLayout.tsxhad none, and several pages (AnnouncementsPage,HomePage,MorePage, ...) have no boundary of their own. An uncaught render error in any of those unmounted the entire React tree to a blank screen with no recovery. This is almost certainly what the Announcements "white space" bug actually was — a render-time throw with nothing above it to catch it. AddedAppErrorBoundaryat the root (main.tsx), mirroring the webapp's version, trimmed to a simple themed "Something went wrong / Reload" screen.CaseActivityFeed(comments/lifecycle/attachments merged),AttachmentsTab's rows,SupportPage's case cards,AnnouncementsPage's announcement cards — all under one list-levelErrorBoundary. A render error in one item was caught by that shared boundary, which unmounts everything below it, not just the offending item. This is exactly how one bad attachment took down the entire comments feed alongside it. AddedListItemErrorBoundary, wrapping each individual item in these four lists so a crash degrades to a small inline "Couldn't display this item" placeholder instead.No changes to any data access, optional chaining, or field-level fallbacks — this is purely containment for whatever still slips through.
Test plan
npx tsc --noEmitnpx eslint .npm run buildSummary by CodeRabbit
Bug Fixes
User Experience