Skip to content

fix: unpin orphaned IPFS CIDs on failed folder registration#59

Merged
FSM1 merged 2 commits into
mainfrom
fix/upload-error-recovery
Feb 7, 2026
Merged

fix: unpin orphaned IPFS CIDs on failed folder registration#59
FSM1 merged 2 commits into
mainfrom
fix/upload-error-recovery

Conversation

@FSM1

@FSM1 FSM1 commented Feb 7, 2026

Copy link
Copy Markdown
Owner

Summary

  • When upload() succeeds but addFiles() fails (e.g., duplicate filename, network error), the already-pinned CIDs are now cleaned up via fire-and-forget unpin calls
  • Quota is refreshed after cleanup so the UI reflects correct usage
  • Applies to both UploadZone and EmptyState components
  • Confirms todo Initial PRD attempt #1 (registering state stuck) was already fixed; moves both resolved todos to done/

Test plan

  • Upload a file with a duplicate name — verify the error is shown and quota does not increase
  • Simulate addFiles failure (e.g., disconnect network after upload completes) — verify CIDs are unpinned
  • Verify normal upload flow still works end-to-end
  • Verify quota refreshes correctly after cleanup

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved file upload error handling to prevent orphaned files in storage; failed uploads now trigger cleanup of uploaded artifacts and refresh quota when appropriate.
  • Tests
    • Added tests covering upload error recovery, orphaned-file cleanup, quota refresh, cancellation paths, and resilience to cleanup failures.

…load

When upload() succeeds but addFiles() fails, the pinned CIDs were never
cleaned up, leaking storage quota. Now the catch block detects this case
by hoisting uploadedFiles before the try block, and fires off unpin
calls for each CID (fire-and-forget, consistent with existing delete
pattern). Quota is refreshed after cleanup.

Both UploadZone and EmptyState catch blocks updated identically.

- Hoist uploadedFiles declaration for catch-block access
- Fire-and-forget unpinFromIpfs for each orphaned CID
- Refresh quota via useQuotaStore.getState().fetchQuota()
- Move completed todo files to done/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Feb 7, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@FSM1 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 19 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Upload components now track uploaded files and perform cleanup (unpin from IPFS and refresh quota) when an upload fails after files were pinned; a new test suite covers error-recovery and orphaned-pin cleanup behaviors.

Changes

Cohort / File(s) Summary
Upload components
apps/web/src/components/file-browser/EmptyState.tsx, apps/web/src/components/file-browser/UploadZone.tsx
Add uploadedFiles tracking; assign upload result to it; on post-upload errors unpin each uploaded CID via unpinFromIpfs and refresh quota via useQuotaStore.
Tests
apps/web/src/stores/__tests__/upload-error-recovery.test.ts
New test suite validating error transitions, orphaned-pin cleanup (unpin + quota refresh), handling when uploadedFiles is undefined, user-cancelled uploads, and non-blocking unpin failures.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant UI as UI Component
participant UploadSvc as Upload Service
participant IPFS as IPFS (unpinFromIpfs)
participant Quota as Quota Store
UI->>UploadSvc: start upload(acceptedFiles)
UploadSvc-->>UI: uploadedFiles (success) / error
alt upload succeeds then registration fails
UI->>IPFS: unpinFromIpfs(cid) for each uploaded file
IPFS-->>UI: ack / error
UI->>Quota: fetchQuota()
Quota-->>UI: updated quota
UI-->>UI: set error state
else upload fails before any pins
UI-->>UI: set error state (no unpin, no quota refresh)
end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

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

- Store transitions from registering to error when addFiles fails
- Orphaned CIDs are unpinned when registration fails after upload
- Quota is refreshed after cleanup
- No cleanup on user cancellation
- No cleanup when upload itself fails (only when registration fails)
- Unpin failures are swallowed (fire-and-forget pattern)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@FSM1 FSM1 force-pushed the fix/upload-error-recovery branch from 2e1d237 to 1ad9f95 Compare February 7, 2026 03:39
@FSM1 FSM1 merged commit 5842b83 into main Feb 7, 2026
10 checks passed
@FSM1 FSM1 deleted the fix/upload-error-recovery branch February 7, 2026 03:45
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.

1 participant