Skip to content

Upload media files sequentially instead of all at once (#432) - #433

Open
willdarbey123-netizen wants to merge 1 commit into
hunvreus:developmentfrom
willdarbey123-netizen:issue/432-sequential-media-uploads
Open

Upload media files sequentially instead of all at once (#432)#433
willdarbey123-netizen wants to merge 1 commit into
hunvreus:developmentfrom
willdarbey123-netizen:issue/432-sequential-media-uploads

Conversation

@willdarbey123-netizen

Copy link
Copy Markdown

Fixes #432.

Problem

Selecting several files at once in a media library (multi-select, or dropping a selection on the drop zone) uploads them concurrently. Each upload is a commit, so the requests race on the branch head and GitHub rejects all but one per round:

... is at <sha> but expected <sha> - https://docs.github.com/rest/repos/contents#create-or-update-file-contents

Some files in the batch land, the rest fail, and it gets worse the more files are selected. One file at a time works.

Cause

handleFiles in components/media/media-upload.tsx is written as a sequential loop, but it awaits the wrong thing:

await toast.promise(uploadPromise, { ... });

sonner's toast.promise() (^2.0.7) returns the toast id synchronously, with an unwrap helper attached, not the promise:

// sonner src/state.ts
return Object.assign(id, { unwrap });

So the await resolves immediately, and because uploadPromise is an IIFE that has already started its fetch, every file in the batch is in flight together.

Change

Keep toast.promise() for the notification, and await the upload itself. A failed file is already reported by the toast, so the loop continues with the remaining files rather than aborting the batch.

One hunk, one file. The rich-text image insert path (components/ui/editor/index.tsx) already awaits onUploadImage directly and is unaffected. components/folder-create.tsx:89 uses the same await toast.promise(...) pattern but as a single call, not a loop, so it is left alone here.

Testing

Not run against a local instance (PostgreSQL + GitHub App). The change is a direct await on the existing promise, and the failure was reproduced repeatedly on app.pagescms.org with 5 to 30 files selected, matching the analysis above. Happy to adjust if you'd prefer await toast.promise(...).unwrap() instead.

🤖 Generated with Claude Code

handleFiles is written as a sequential loop, but `await toast.promise()`
does not wait for the upload: sonner's toast.promise() returns the toast
id synchronously (with an `unwrap` helper attached), not the promise. So
the loop moved on immediately and every file in a batch was in flight at
the same time.

Each upload is its own commit, and concurrent commits to the same branch
race on the branch head. GitHub rejects all but one per round with
"is at <sha> but expected <sha>", so a multi-file upload landed some
files and failed the rest.

Await the upload promise itself. A failed file is already reported by
the toast, so the loop carries on with the remaining files rather than
aborting the batch.

Fixes hunvreus#432

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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