Skip to content

fix(web): guard unguarded data derefs causing work-item and layout crashes - #9546

Merged
sriramveeraghanta merged 11 commits into
previewfrom
fix/crash-guards-issue-peek-labels
Aug 4, 2026
Merged

fix(web): guard unguarded data derefs causing work-item and layout crashes#9546
sriramveeraghanta merged 11 commits into
previewfrom
fix/crash-guards-issue-peek-labels

Conversation

@codingwolf-at

@codingwolf-at codingwolf-at commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Description

Customers reported full-page crashes when opening work items and switching layouts (Slack thread, Aug 4). Traced the crashes to a recurring pattern: components dereferencing API/store data (.find, .map, .filter, property access) with only a null-guard (?.), not a shape guard — so a stale relation, a malformed/paginated response, or a member with an incomplete record throws deep inside a render and takes the whole page down via the top-level route error boundary.

This PR:

  • Fixes 6 concrete unguarded-dereference spots across the issue peek/detail view, sub-issue creation, description version history, label rendering, integrations list, and profile activity.
  • Adds a local LayoutErrorBoundary around the issue layout switcher (List/Kanban/Spreadsheet/Calendar/Gantt) so a crash in one layout's render degrades to an inline "Try again" panel instead of crashing the entire app — this contains the still-unreproduced "switching to columns crashes the page" report without requiring an exact repro.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots and Media (if applicable)

NA - no UI change

Test Scenarios

  • Open a work item whose creator record has a missing/null display_name — peek and full detail view should render instead of crashing (peek-overview/properties.tsx).
  • Open a work item that has a label id no longer present in the label map (deleted label) — label list in spreadsheet column and issue properties should render without the stale label instead of crashing.
  • Add sub-issues to a work item; verify state distribution and issue list update correctly, and that the flow doesn't throw if the backend omits sub_issues/state_distribution in the response.
  • Open a work item's description version history — verify it renders (and degrades gracefully, not crashes) if the versions list response is malformed.
  • Force a layout render error (e.g. temporarily throw in a Kanban/Spreadsheet child) and confirm switching to that layout shows the local "Try again" fallback instead of the full-page "Looks like something went wrong" screen, and that switching to a different layout afterward recovers cleanly.
  • Exporter previous-exports polling and single-integration-card install/remove flows still work when the underlying list is a normal array (regression check for the added Array.isArray guards).

References

  • Slack thread: customer-reported crashes on opening work items, switching to columns view, and Modules (Aug 4, 2026)
  • Sentry issue PLANE-WEB-5DC (d.find is not a function) was investigated as a possible root cause; the specific code path it pointed to no longer exists in this codebase, but it confirmed the defect class (unguarded .find() on API-sourced data) this PR addresses.

Summary by CodeRabbit

  • New Features

    • Added error recovery for individual layout views, including a retry option to keep the rest of the page available.
    • Improved previous export handling with clearer loading, populated, and empty states.
  • Bug Fixes

    • Improved handling of missing or invalid data in labels, user profiles, integrations, sub-issues, and activity results.
    • Added safeguards for unavailable optional data and malformed responses to prevent unexpected errors.

Updated the mapping of label IDs to ensure that only defined label options are included in the defaultLabelOptions array across multiple components. This change enhances the robustness of the label handling in the IssueProperties and SpreadsheetLabelColumn components, as well as in the PeekOverviewProperties component.
Updated multiple components to include checks for array types before accessing results. This change enhances stability by preventing potential runtime errors when results are undefined or not an array. Affected components include DescriptionVersionsRoot, PrevExports, SingleIntegrationCard, ProfileActivity, and IssueSubIssuesStore.
Updated the IssueLayoutHOC component to include LayoutErrorBoundary, enhancing error handling by wrapping the children. This change aims to provide a more robust user experience by catching layout-related errors effectively.
@codingwolf-at
codingwolf-at marked this pull request as draft August 4, 2026 14:42
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3685b071-483b-47b3-b23b-0bcb0116aa00

📥 Commits

Reviewing files that changed from the base of the PR and between bbf74e1 and 54020f8.

📒 Files selected for processing (3)
  • apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx
  • apps/web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx
  • apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx
  • apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx
  • apps/web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx

📝 Walkthrough

Walkthrough

This PR adds LayoutErrorBoundary for issue layout render failures and adds defensive checks for API collections, label references, nested properties, and activity results. Export polling now uses memoized refresh handling and explicit loading, populated, and empty states.

Changes

Layout resilience and defensive data handling

Layer / File(s) Summary
LayoutErrorBoundary implementation
apps/web/core/components/common/layout-error-boundary.tsx
Adds localized fallback UI, error logging, retry handling, and child remounting.
Layout error boundary integration
apps/web/core/components/issues/issue-layouts/issue-layout-HOC.tsx
Wraps layout children in LayoutErrorBoundary and resets it when layout changes.
Collection and response validation
apps/web/core/components/core/description-versions/root.tsx, apps/web/core/components/exporter/prev-exports.tsx, apps/web/core/components/integration/single-integration-card.tsx, apps/web/core/store/issue/issue-details/sub_issues.store.ts
Validates array-shaped data before array operations and applies defined fallback values. Export refresh handling is memoized and loading cleanup is guaranteed.
Label and nested property safety
apps/web/core/components/issues/issue-layouts/..., apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx, apps/web/core/components/issues/peek-overview/properties.tsx, apps/web/core/components/common/activity/user.tsx, apps/web/core/components/profile/overview/activity.tsx
Filters missing labels, guards display_name access, and checks activity results before rendering collection content.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • makeplane/plane#9530: Related to React compatibility changes involving the layout error boundary integration.

Suggested reviewers: prateekshourya29

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant IssueLayoutHOC
  participant LayoutErrorBoundary
  participant LayoutView
  IssueLayoutHOC->>LayoutErrorBoundary: render children with layout key
  LayoutErrorBoundary->>LayoutView: render layout view
  LayoutView-->>LayoutErrorBoundary: throw render error
  LayoutErrorBoundary-->>User: show localized fallback and retry button
  User->>LayoutErrorBoundary: click retry
  LayoutErrorBoundary->>LayoutView: remount children
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: guarding unsafe data dereferences and containing layout crashes.
Description check ✅ Passed The description includes the required sections, explains the fix, identifies the change type, and lists specific test scenarios and references.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/crash-guards-issue-peek-labels

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

React Doctor found 3 new issues in 3 files · 3 warnings · score 91 / 100 (Great) · 1 fixed · vs preview

3 warnings

core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx

  • ⚠️ L14 Import from a barrel file no-barrel-import

core/components/issues/peek-overview/properties.tsx

  • ⚠️ L42 Import from a barrel file no-barrel-import

core/components/issues/workspace-draft/draft-issue-properties.tsx

  • ⚠️ L31 Import from a barrel file no-barrel-import

Reviewed by React Doctor for commit 54020f8. See inline comments for fixes.

Refactored the handleRefresh function in the PrevExports component to use useCallback, improving performance by memoizing the function. Additionally, updated the useEffect dependency array to include handleRefresh, ensuring the effect runs correctly when dependencies change. This change enhances the efficiency of the component's refresh logic.
Comment thread apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx Outdated
@codingwolf-at codingwolf-at changed the title Fix/crash guards issue peek labels fix(web): guard unguarded data derefs causing work-item and layout crashes Aug 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/web/core/components/integration/single-integration-card.tsx (1)

109-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove any from the integration lookup.

The changed callback uses (i: any). This bypasses strict type checking for integration_detail. Type the SWR result as IWorkspaceIntegration[], or annotate the callback with IWorkspaceIntegration, and let find infer the element type.

Proposed fix
-  ? workspaceIntegrations.find((i: any) => i.integration_detail.id === integration.id)
+  ? workspaceIntegrations.find((i: IWorkspaceIntegration) => i.integration_detail.id === integration.id)

As per coding guidelines, TypeScript strict mode is enabled and all TSX files must be typed.

🤖 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/web/core/components/integration/single-integration-card.tsx` around
lines 109 - 111, Remove the explicit any annotation from the callback in the
isInstalled integration lookup. Type workspaceIntegrations as
IWorkspaceIntegration[] or annotate the callback parameter as
IWorkspaceIntegration so find infers and validates integration_detail.id under
strict TypeScript typing.

Source: Coding guidelines

🤖 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 `@apps/web/core/store/issue/issue-details/sub_issues.store.ts`:
- Around line 169-170: Update the sub-issue response handling around
subIssuesStateDistribution and subIssues to explicitly validate that response
exists and that response.sub_issues is the expected array shape before either
map call. Handle grouped-object responses through the existing runtime
validation path rather than relying on nullish fallback or a simple
Array.isArray default, and preserve empty results for invalid or missing data.

---

Nitpick comments:
In `@apps/web/core/components/integration/single-integration-card.tsx`:
- Around line 109-111: Remove the explicit any annotation from the callback in
the isInstalled integration lookup. Type workspaceIntegrations as
IWorkspaceIntegration[] or annotate the callback parameter as
IWorkspaceIntegration so find infers and validates integration_detail.id under
strict TypeScript typing.
🪄 Autofix

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: d8b5265e-e75b-4892-86d8-1fd0cd273e77

📥 Commits

Reviewing files that changed from the base of the PR and between ed61f99 and c845542.

📒 Files selected for processing (10)
  • apps/web/core/components/common/layout-error-boundary.tsx
  • apps/web/core/components/core/description-versions/root.tsx
  • apps/web/core/components/exporter/prev-exports.tsx
  • apps/web/core/components/integration/single-integration-card.tsx
  • apps/web/core/components/issues/issue-layouts/issue-layout-HOC.tsx
  • apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx
  • apps/web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx
  • apps/web/core/components/issues/peek-overview/properties.tsx
  • apps/web/core/components/profile/overview/activity.tsx
  • apps/web/core/store/issue/issue-details/sub_issues.store.ts

Comment thread apps/web/core/store/issue/issue-details/sub_issues.store.ts Outdated
…d error messaging

Refactored the LayoutErrorBoundary component to include a dedicated LayoutErrorFallback for better error presentation. Added a retry mechanism that allows users to attempt to reload the content after an error occurs. This change improves user experience by providing clearer messaging and a more interactive way to recover from errors.
…ents

Refactored the defaultLabelOptions logic in multiple components to use flatMap for better handling of undefined labels. Additionally, updated array checks in the PrevExports component to ensure results are properly validated before access. These changes enhance the robustness and stability of the components, preventing potential runtime errors.
… handling

Updated the ProfileActivity component to enhance the loading state management and streamline the rendering of user activity results. The refactor includes a more efficient check for userProfileActivity, ensuring that loading indicators and empty states are displayed correctly. This change improves the user experience by providing clearer feedback during data fetching and handling scenarios with no activity results.
…ub-issues store

Updated the SingleIntegrationCard component to use a specific type for workspace integrations, enhancing type safety. Additionally, refactored the subIssues assignment in the IssueSubIssuesStore to ensure it correctly checks for an array before assignment, improving stability and preventing potential runtime errors.
@codingwolf-at
codingwolf-at marked this pull request as ready for review August 4, 2026 15:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@apps/web/core/components/exporter/prev-exports.tsx`:
- Around line 49-52: Update handleRefresh to await mutate inside a
try/catch/finally flow, logging the typed error in catch and always calling
setRefreshing(false) from finally. Preserve the existing EXPORT_SERVICES_LIST
request and refresh state initialization.
🪄 Autofix

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: d51e886e-0b6a-4bfa-b557-9f511d389238

📥 Commits

Reviewing files that changed from the base of the PR and between c845542 and ff9141f.

📒 Files selected for processing (9)
  • apps/web/core/components/common/activity/user.tsx
  • apps/web/core/components/common/layout-error-boundary.tsx
  • apps/web/core/components/exporter/prev-exports.tsx
  • apps/web/core/components/integration/single-integration-card.tsx
  • apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx
  • apps/web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx
  • apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx
  • apps/web/core/components/profile/overview/activity.tsx
  • apps/web/core/store/issue/issue-details/sub_issues.store.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/web/core/store/issue/issue-details/sub_issues.store.ts
  • apps/web/core/components/integration/single-integration-card.tsx
  • apps/web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx
  • apps/web/core/components/profile/overview/activity.tsx
  • apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx

Comment thread apps/web/core/components/exporter/prev-exports.tsx Outdated
Refactored the handleRefresh function in the PrevExports component to include error handling during the refresh process. The function now uses async/await for better readability and ensures that any errors during the mutation are logged, improving the robustness of the component's refresh logic.
Multi-line flatMap guard needed reformatting to satisfy oxfmt.
Adjusted the formatting of the defaultLabelOptions logic in the DraftIssueProperties component to maintain consistency with the project's coding standards. This change enhances readability without altering functionality.
@sriramveeraghanta
sriramveeraghanta merged commit fa02716 into preview Aug 4, 2026
14 checks passed
@sriramveeraghanta
sriramveeraghanta deleted the fix/crash-guards-issue-peek-labels branch August 4, 2026 18:51
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.

3 participants