Avatar video 400: script must include at least one word

A Sume talking-video request with an empty or whitespace-only script returns 400 invalid_request, with no job or ledger entry. Guard blank template fields.

4 min readSume
All posts

A Sume avatar video request whose script is empty or only whitespace returns 400 invalid_request with the message Avatar video script must include at least one word. The check runs during validation, so no job is created and no usage is recorded: the API tests assert that the ledger has no entry after the response. You pay nothing for the failed call, and nothing is queued.

The request shape is on Generate avatar video, and the way Sume decides what to reserve before work starts is on Generation admission, both read 2026-10-05.

Where the word count matters

The rule is about words, not characters. A script of spaces, tabs or newlines has length but no words, and counts as empty. The duration limits that come right after it use the same word count to estimate how long the speech will run.

Whitespace is the trap. A script field that contains a newline from a spreadsheet cell, a single space from a form, or an empty paragraph from a rich text editor looks filled in to a human and to a simple truthiness check in many languages, since a string of spaces is non-empty. Trimming before the check is the habit that avoids sending it. The word count the API uses is the same one it applies to the duration estimate, so a script that passes the empty check is already a candidate for the 4 to 60 second window.

Script inputs and their results, read 2026-10-05
ScriptResult
"" (empty string)400 invalid_request, at least one word required
" \n " (whitespace only)400 invalid_request, at least one word required
One short sentenceAccepted if the estimated duration lands in the 4 to 60 second window
A 169-word script400: estimated at 64 seconds; maximum is 60 seconds

Guard the template before the call

The usual cause is a template. A script like Hi {{first_name}}, {{offer_text}} is fine when both variables are set and an empty-looking request when a CRM row has blank fields. Render the template, trim it, and refuse to send an empty result.

import re

def render(template, values):
    return re.sub(r"\{\{(\w+)\}\}", lambda m: values.get(m.group(1), ""), template)

def script_or_none(template, values):
    text = " ".join(render(template, values).split())
    return text if text else None

print(script_or_none("{{greeting}} {{offer}}", {"greeting": "Hi there,", "offer": "we saved you a seat."}))
print(script_or_none("{{greeting}} {{offer}}", {}))

The same guard for scenes

The second call prints None, which is your signal to skip the row and log it instead of calling the API. Skipping is cheaper than sending, since even a free rejection costs a round trip and an error log line, and you probably want a person to look at a blank field.

Do the same for the multi-scene form. In video_inputs, a spoken scene needs a script or input_text, and a silent scene uses voice.type: silence with a duration. A scene with an empty script is not a silent scene; if you want a pause, say so with silence.

What comes next

Duration errors are the next ones you will meet. Sume estimates speech length from the word count and requires the total to fall in a window of 4 to 60 seconds, the same window the docs give for multi-scene requests. A long script is refused with a message that states the estimate and the maximum. For long content, see what to do past 60 seconds, and for what each length costs, see the price ladder.

A useful test for your own client is to feed it the three inputs from the table and assert that none of them reaches the network. The first two should be caught by your guard, and the third should pass through and be judged by the API. Writing that test once protects a campaign run from a data problem you would otherwise find only after a batch of 400 responses.

Do not retry a 400

Because the failed call is not a job, there is nothing to cancel, poll or reconcile. If your client retries on any 4xx, make 400 a permanent error and do not retry it: an empty script stays empty. Retries are for network failures, and the idempotency post covers how to do them without paying twice.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume