fal cancel returns 202 or 400: how Sume's cancel 409 differs
fal's queue cancel answers 202 CANCELLATION_REQUESTED, 400 ALREADY_COMPLETED or 404. Sume's cancel works only before generation starts, else 409.

fal's cancel call is a PUT on the request's /cancel URL and answers 202 with CANCELLATION_REQUESTED, 400 with ALREADY_COMPLETED, or 404 with NOT_FOUND. Sume's is a POST /v1/jobs/{job_id}/cancel that succeeds only before generation work starts; after that it returns 409 job_generation_already_started and the job runs to completion. Both treat a request that is already running as not reliably stoppable, but they report it differently, so a handler ported from one needs a new branch for the other.
fal facts come from the cancel section of its Queue API page; Sume facts come from Jobs and results and the core workflow page. The fal page was read on 2026-10-02.
What does fal do when you cancel?
It depends on the request's state. A request still in IN_QUEUE is removed immediately and never processed. A request already IN_PROGRESS gets a cancellation signal sent to the runner, and fal says it may still complete if the app does not handle cancellation; whether the code stops depends on whether the app implements a cancel endpoint.
The response carries both an HTTP status and a JSON body. A 202 means the cancel was accepted, not that work stopped. With fal's SDK, handler.cancel() returns silently on 202 and raises on 400 or 404.
What does Sume do when you cancel?
A job that has not started generating is canceled and ends in the terminal canceled status. Once generation has started, Sume returns 409 job_generation_already_started with details.cancelable: false, and the job runs to completion. Cancelling a job that is already canceled is idempotent and returns the same canceled job.
The core workflow page says provider-backed generation can reserve estimated USD usage, capture the actual cost on success, and refund on failure or cancellation before capture. So the cancel that works is the one that refunds; a 409 means the work is already running and will be billed like any completed job.
Which statuses map to which?
The table lines up the documented cases. A fal 202 is a request, so poll afterwards; on Sume, read the job status after cancel to confirm canceled.
| Situation | fal | Sume |
|---|---|---|
| Not started | Request removed from the queue; 202 | Job ends canceled |
| Already running | 202 CANCELLATION_REQUESTED; may still complete | 409 job_generation_already_started, details.cancelable: false; runs to completion |
| Already finished | 400 ALREADY_COMPLETED | Not stated for completed jobs on the page; read the job status |
| Already canceled | Not stated on the page | Idempotent; returns the same canceled job |
| Unknown id | 404 NOT_FOUND | Not stated on the page |
How should a client handle both?
Treat cancel as a request, then read state. After a cancel call, fetch the job (GET /v1/jobs/{job_id}/status on Sume) and branch on the terminal flag rather than on the cancel response alone. On Sume, a 409 is not a failure to retry: stop trying to cancel and wait for the job to finish, because it will still bill. On fal, a 202 for an in-progress request should be followed by a status check for the same reason.
A client-side timeout cancels nothing on Sume. Sume's docs say the job keeps running and billing after you stop watching, so store the job id and either pick it back up from status_url or cancel before it starts.
Sources
Related posts
More in Comparisons
- fal media lasts 7 days by default; Sume URLs do not expire
fal keeps generated media on its CDN for at least 7 days and lets you set a lifecycle per request. Sume media.sume.com URLs do not expire. What to store.
- fal proxy with x-fal-target-url vs keeping a Sume key on your server
fal documents an 8-step proxy that reads x-fal-target-url and adds a Key header. Sume has no browser SDK: you proxy your own route. A minimal comparison.
- fal's hint pins a runner; Sume has no runner choice
fal's queue submit takes a hint that routes to the runner used before. Sume hides providers and runners. What to do when you need affinity.
- fal queue has no size limit: what Sume does instead (queue_full)
fal's queue docs say there is no queue size limit and requests are never dropped. Sume caps accepted jobs per plan and returns 429 queue_full. What that means.
Written by Sume