An uploaded Sume asset you never complete: what happens

A pending_upload asset has a 15-minute URL by default. After the window and a one-hour grace, a reaper deletes the object and marks the row failed.

4 min readSume
All posts

If you PUT bytes to a Sume upload URL and never call complete, the asset stays pending_upload until the URL window closes (900 seconds by default). Completing after that returns 409 asset_upload_expired and deletes the object. A background reaper then removes anything left more than an hour past the window: it deletes the stored object and moves the row to failed. These routes are implemented but hidden from the public OpenAPI document, so treat them as a working surface rather than a documented contract; for generation inputs Sume's docs still prefer public HTTPS media URLs.

The numbers below are defaults from the API configuration and reaper code on Sume's main branch, read 2026-10-11.

How long is the upload window?

The upload-url response includes upload.expires_at and upload.max_bytes. The window defaults to 900 seconds, and the byte limit defaults to 2 GiB; both are deployment settings. The same expires_at is stored on the asset as upload.expires_at, so a later GET /v1/assets/{id} shows when the window closes.

A request over the byte limit never gets a URL: upload-url answers 413 asset_too_large before creating anything.

What does the reaper do?

Before the reaper existed, an upload that was PUT and never completed kept its row in pending_upload and its bytes in the media bucket forever. Now every tick lists pending rows whose window closed more than 60 minutes ago, in batches of 100 with at most 10 batches per tick.

For each row it deletes the object first and only then marks the row failed. A failed delete leaves the row pending so the next tick retries. If another live row points at the same object key, which happens when a thread is forked, the object is kept and only the expired row is failed. The tick runs every 10 minutes by default, and setting the interval to 0 turns it off.

Lifecycle of an uncompleted upload, defaults from the code (read 2026-10-11)
Time after upload-urlState
0 to 15 minutespending_upload, PUT and complete allowed
After 15 minutescomplete returns 409 asset_upload_expired and deletes the object
After about 75 minuteseligible for the reaper on its next tick
After the reaper runsobject deleted, status failed

How do I find and clean up pending uploads?

List with status=pending_upload to see uploads still open, and status=failed to see what the reaper closed. Nothing needs to be done for an abandoned upload; the reaper handles it. If your job still needs the file, request a new upload URL and start again, because an expired asset cannot be revived.

Completion of a ready asset is idempotent and returns the asset again, so retrying a complete call whose response you lost is safe.

curl -s "https://api.sume.com/v1/assets?status=pending_upload&limit=100" \
  -H "Authorization: Bearer $SUME_API_KEY" \
  | jq -r '.data.assets[] | [.id, .upload.expires_at] | @tsv'

Sources

Related posts

More in Developers

All Developers posts

Written by Sume