Skip to content

Fix: Deleting the attachment from the card lead to error page#184

Open
Rajat-Dabade wants to merge 2 commits into
mainfrom
fix-attachment-delete-issue
Open

Fix: Deleting the attachment from the card lead to error page#184
Rajat-Dabade wants to merge 2 commits into
mainfrom
fix-attachment-delete-issue

Conversation

@Rajat-Dabade

@Rajat-Dabade Rajat-Dabade commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Deleting an attachment after a hard refresh would successfully call the API and show the success flash message, but then immediately redirect the user to the error page.

When an attachment is deleted, the server sends an update through WebSocket saying the attachment is deleted. The Redux store updates correctly and removes that attachment. At that exact moment, the AttachmentElement component is still on the screen. So when the selector runs again, it tries to find the attachment using the old blockId, but it’s already gone, and now it gets undefined. Then the code tries to access .uploadingPercent on that undefined value, which causes a crash. This is caught by ErrorBoundary, and redirects the user to /error?id=unknown.

Fix: Added optional chaining fallback so the selector safely returns 0 when the block no longer exists in the store

Steps to Reproduce

  • Open a board and open a card that has an attachment
  • Hard refresh the page (Cmd+Shift+R / Ctrl+Shift+R)
  • Open the card again and click the delete icon on the attachment
  • Confirm the deletion

Before fix: redirected to the error page despite the API succeeding
After fix: attachment is deleted cleanly with the success flash message

Ticket Link

https://mattermost.atlassian.net/browse/MM-68059

Change Impact: 🟢 Low

Regression Risk: Minimal. Changes are confined to a single Redux selector and a reducer guard in webapp/src/store/attachments.ts to defensively handle missing attachment entries (returns 0 instead of accessing undefined). No behavioral changes for valid states, no shared utilities or auth/data persistence touched, and blast radius is limited to attachment rendering flows.

QA Recommendation: Minimal manual QA. Validate the reported scenario (hard refresh, reopen card with attachment, delete attachment) to ensure deletion succeeds and no error-page redirect occurs. Automated rollback is straightforward.

Generated by CodeRabbitAI

@Rajat-Dabade Rajat-Dabade self-assigned this Apr 2, 2026
@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3638606c-b855-4593-b07d-e79ac3edd61d

📥 Commits

Reviewing files that changed from the base of the PR and between c8d75b6 and d380097.

📒 Files selected for processing (1)
  • webapp/src/store/attachments.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • webapp/src/store/attachments.ts

📝 Walkthrough

Walkthrough

Guarded attachment updates in the attachments store: the updateUploadPrecent reducer now skips when the attachment entry is missing, and the getUploadPercent(blockId) selector returns 0 if the attachment or its uploadingPercent is undefined.

Changes

Cohort / File(s) Summary
Attachment store changes
webapp/src/store/attachments.ts
Reducer updateUploadPrecent now checks for existence of state.attachments[blockId] before mutating. Selector getUploadPercent(blockId) uses optional lookup and returns 0 when the attachment or uploadingPercent is absent.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Suggested labels

3: QA Review

Suggested reviewers

  • yasserfaraazkhan
  • devinbinnie
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: preventing an error page when deleting an attachment from a card by safely handling undefined attachment entries.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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-attachment-delete-issue

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

@Rajat-Dabade Rajat-Dabade added the 2: Dev Review Requires review by a core committer label Apr 2, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
webapp/src/store/attachments.ts (1)

48-50: Consider adding similar defensive check to the reducer.

The reducer directly accesses state.attachments[action.payload.blockId] without verifying the attachment exists. While this action is typically dispatched during upload (when the attachment should exist), applying the same defensive pattern would provide consistency and guard against edge cases.

🛡️ Optional hardening
         updateUploadPrecent: (state, action: PayloadAction<{blockId: string, uploadPercent: number}>) => {
-            state.attachments[action.payload.blockId].uploadingPercent = action.payload.uploadPercent
+            if (state.attachments[action.payload.blockId]) {
+                state.attachments[action.payload.blockId].uploadingPercent = action.payload.uploadPercent
+            }
         },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@webapp/src/store/attachments.ts` around lines 48 - 50, The reducer
updateUploadPrecent directly indexes state.attachments[action.payload.blockId]
without checking existence; add a defensive guard in updateUploadPrecent that
first reads const attachment = state.attachments[action.payload.blockId] and if
(!attachment) return (or no-op), otherwise set attachment.uploadingPercent =
action.payload.uploadPercent so the reducer won't throw when the attachment is
missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@webapp/src/store/attachments.ts`:
- Around line 48-50: The reducer updateUploadPrecent directly indexes
state.attachments[action.payload.blockId] without checking existence; add a
defensive guard in updateUploadPrecent that first reads const attachment =
state.attachments[action.payload.blockId] and if (!attachment) return (or
no-op), otherwise set attachment.uploadingPercent = action.payload.uploadPercent
so the reducer won't throw when the attachment is missing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 241ef987-5e56-4382-816f-9208c4187cc9

📥 Commits

Reviewing files that changed from the base of the PR and between b87f32e and c8d75b6.

📒 Files selected for processing (1)
  • webapp/src/store/attachments.ts

@harshilsharma63 harshilsharma63 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need to add tests for this.

@mattermost-build

Copy link
Copy Markdown
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2: Dev Review Requires review by a core committer Lifecycle/1:stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants