Sume TTS source errors: which are safe to retry (status table)
Every tts_ error code in Sume's script-source API with its HTTP status, whether it charges, and whether a retry can help. A table for client error handling.

Sume's script-source API for text-to-speech returns a small, fixed set of tts_ error codes. The question for client code is simple: retry, fix the request, or re-read state first. Every code below is raised before a provider call is dispatched, so a failed request creates no job and is not billed. Branch on code, not on the message wording.
Sume bills Sume TTS at $0.0475 per 1,000 characters, rounded up to the cent per job, and only for jobs that run.
Code by code
| Code | HTTP | Retry as is? | What to do |
|---|---|---|---|
| tts_text_source_required | 400 | No | Send exactly one of transcript or transcript_source; source needs a thread. |
| tts_text_source_conflict | 400 | No | Remove one of the two inputs, or fix a malformed transcript_source. |
| tts_source_edit_unchanged | 400 | No | The replacement text equals the current words; skip the edit. |
| tts_source_edit_interactive_only | 400 | No | Speech edits require an interactive thread. |
| tts_source_not_found | 404 | No | Re-read the manifest; check thread, revision, sentence and job ids. |
| tts_source_revision_mismatch | 409 | After re-reading | Fetch the current revision, reapply your change, resubmit with the new id. |
| tts_sentence_selection_invalid | 422 | No | Make the selection contiguous, complete and in order; list each job once. |
| tts_source_too_large | 422 | No | Split the selection so each job resolves to 20,000 characters or fewer. |
| tts_source_integrity_mismatch | 422 | No | Regenerate the job from the current revision or pass explicit sentence_ids. |
| tts_source_store_unavailable | 503 | Yes, with backoff | Durable source storage is unavailable; retry the same request later. |
Idempotency
Generate calls take an idempotency-key header. Keep the same key when you retry the same request after a 503, so one logical line becomes one job. Change the key when you change the request, since the key names the request, not the attempt.
A small handler
Only the 503 is retried blindly. The 409 triggers a re-read.
RETRY_BLIND = {"tts_source_store_unavailable"}
REREAD = {"tts_source_revision_mismatch"}
def action(status, code):
if code in RETRY_BLIND or status == 503:
return "retry-with-backoff"
if code in REREAD:
return "reread-manifest"
return "fix-request"
print(action(409, "tts_source_revision_mismatch"))
print(action(503, "tts_source_store_unavailable"))
print(action(422, "tts_source_too_large"))Sources
Related posts
More in Developers
- Which Sume video models take 9:16? Query the catalog, do not guess
GET /v1/videos/models lists supported_aspect_ratios and supported_durations per model. A jq filter picks the vertical models that reach your platform's length.
- Which wait to use for a 30 second clip: sync, webhook or a poll
A table of the waits Sume documents for a 30 s clip: a bounded sync of up to 30 s, webhooks with retries, and a roughly 20 minute client deadline. Which fits.
- Which workspace does a Sume MCP call spend from? Key or sign-in
The API key or the signed-in account selects the workspace; Sume tools never take a workspace id from the prompt. Confirm it with account_me before you spend.
- Word timestamps to video frame numbers at 29.97 fps in Python
Sume STT words[] carry start and end in seconds. Convert them to frame indexes with exact 30000/1001 math so cuts do not drift on long timelines.
Written by Sume