fix(frontend): keep the attachments that uploaded when one in the batch fails - #260
Merged
Merged
Conversation
…ch fails Attaching several files at once and having one fail discarded every file that had already uploaded. `addAttachments` accumulated into a local `staged` array and merged it into the composer draft only after the loop finished. Any throw inside the loop -- an oversized file, the combined-size ceiling, or a staging request failing -- jumped straight to the handler, and `staged` went out of scope unused. Those files were not merely missing from the UI. Each had already been uploaded and had a real backend artifact holding retention, so they were orphaned until it expired, and the user had to re-add the rest by hand with no indication which ones had made it. The merge is now a small helper called on both paths, so a partial batch keeps what genuinely uploaded, and the message says as much rather than reporting a bare failure. The same function also dropped any files beyond the remaining slots in silence: `files.slice(0, remaining)` with a message only in the fully-full case. Choosing nine files with eight slots attached eight and looked exactly like attaching nine. It now says how many were taken. The hardcoded "eight" in the neighbouring message became MAX_CHAT_ATTACHMENTS while I was there, since the new message reads from the same constant. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Attaching several files at once and having one fail discards every file that already uploaded.
Those files are not merely missing from the UI. Each had already been uploaded and had a real backend artifact holding retention, so they are orphaned until it expires — and the user has to re-add the rest by hand, with no indication which ones made it.
Root cause
addAttachmentsaccumulated into a localstagedarray and merged it into the composer draft only after the loop finished:Any throw inside the loop — an oversized file, the combined-size ceiling, or a staging request failing — jumps straight to the handler, and
stagedgoes out of scope unused. Three separate conditions reach it, and the second and third can only trigger after earlier files have already uploaded.The merge is now a small helper called on both paths, so a partial batch keeps what genuinely uploaded and the message says so instead of reporting a bare failure.
A second, quieter one in the same function
Files beyond the remaining slots were dropped in silence — a message existed only for the fully-full case (
!remaining). Choosing nine files with eight slots attached eight and looked exactly like attaching nine.It now reports how many were taken. The hardcoded
"eight"in the neighbouring message becameMAX_CHAT_ATTACHMENTSwhile I was there, since the new message reads from the same constant and the two must not drift.Verification
Two new tests, both failing against the unfixed code:
Only 8 of 9 files were attachednpm test -- --runnpm run typechecknpm run lintpython -m pytest -qCompatibility and rollback
Frontend only, confined to one function. No API contract, stored data, or migration. The all-succeed path behaves exactly as before. Reverting the commit restores the previous behaviour exactly.
Unrelated observation
While running the backend suite for this change I hit a rare pre-existing flake:
test_code_execution.py::test_cancelling_an_approved_but_unleased_code_job_reaches_a_terminal_statusfailed once in roughly five full-suite runs, then passed on four consecutive full runs here and two onmain. This change is frontend-only and cannot affect it, but a non-deterministic test on a cancellation path is worth a look on its own — flagging it rather than leaving it in the scrollback.🤖 Generated with Claude Code