format_not_forkable 409 in the Sume API: what it means and the fix
Sume returns 409 format_not_forkable when the id you called names a built-in capability, not a Format card. How to tell, and which ids to call instead.

What does 409 format_not_forkable mean? According to the Sume Formats errors page, it means you addressed a built-in capability rather than a Format, and the fix is to call a Format by Sume or one of your own. A Format is a saved recipe you can address as {handle}/{slug} or by its opaque skl_... id. A built-in capability is something the platform ships that is not packaged as a Format card, so the run endpoints refuse to treat it as one.
You will meet this error when a script builds the address from a list that mixes real Formats with other ids, which is easy to do with a catalog sheet.
Which addresses work
The curated Formats by Sume live under the reserved sume handle, such as sume/sume-product-commercial and sume/sume-video-hook from the catalog, and the API reference says they are directly invokable and never return this error. Your own Formats are {your-handle}/{slug}. Both can be called with POST /v1/formats/{handle}/{slug}/runs and both can be queued with .../bulk-runs.
Handle renames resolve for 90 days, so an old handle still works for a while, but a capability id never will. If a call fails with format_not_forkable it will keep failing: retrying is wasted time.
Triage in four steps
- Read
error.codefirst. A 409 has several meanings on a run submit, includingformat_run_in_progress,format_inactive,format_api_trigger_disabled,previous_run_not_terminalandidempotency_conflict. - If the code is
format_not_forkable, check the id you sent against the Formats you can list withGET /v1/formats. - Swap in a
sume/{slug}catalog Format, or create your own and call that. - Do not retry the same id; the answer will not change.
Where it hides in a pipeline
The usual source is a spreadsheet of identifiers that grew by copy and paste. One row holds a catalog Format, another holds a name that you remember from a product page, and the loop calls them all with the same endpoint. The first call that names a capability returns the 409 and the loop stops or, worse, logs and continues.
Make the failure loud. Treat any 409 with this code as a data error in your list, not as a transient fault, and put the offending id in the alert. In a bulk job the address is part of the URL, so the error shows up on the create call, before a queue exists, and costs nothing.
If you wanted a capability's output, use a Format that wraps it, from the Formats catalog or one you create with POST /v1/formats, then call that.
Guard a bulk job
In a bulk create, a bad address fails the create call before any queue exists, so nothing is dispatched. The check below validates a list of ids against the known shape before the first request goes out: the {handle}/{slug} form, or an skl_ id. It cannot know which ids are capabilities, so keep a list of the ones you have verified.
import re
SHAPE = re.compile(r"^([a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*|skl_[A-Za-z0-9]+)$")
verified = {"sume/sume-video-hook", "mybrand/holiday-promo"}
requested = ["sume/sume-video-hook", "mybrand/holiday-promo", "Some Capability"]
for ident in requested:
if not SHAPE.match(ident):
print("bad shape:", ident)
elif ident not in verified:
print("unverified, check before bulk:", ident)
else:
print("ok:", ident)Sources
Related posts
More in Developers
- Format webhook 3xx: Sume does not follow redirects, use the final URL
A webhook endpoint that redirects counts as a failed delivery attempt. Register the final HTTPS URL, mind www and trailing-slash redirects, then redeliver.
- Python verifier for Sume webhooks: stale timestamps, empty secret
A short Python function that verifies a Sume webhook: five-minute timestamp window, constant-time HMAC compare and a hard refusal of an empty secret.
- Forward verified Sume webhooks to Kafka, keyed by job_id
Verify the sume-v1 signature, refuse an empty secret, then produce each job event to Kafka with job_id as the key so retries land in one partition.
- Freeze a TTS preset so every episode sounds the same
Keep one JSON preset for a recurring voiceover: avatar handle, language, speed 0.6-1.5, volume 0.5-2, output format. Sume also records these values on each job.
Written by Sume