Optional field in a Sume Format output_schema: use a null union
A Sume output_schema has no optional properties. List every key in required and give optional ones a type of ["string","null"], or the create fails with 400.

You cannot make a property optional in a Sume Format output_schema. Every declared property must also appear in required, and "may be missing" is written as a nullable union such as "type": ["string", "null"]. A schema that declares a property without requiring it is refused at create with 400 output_schema_invalid and a required_completeness violation. Nothing runs and nothing is charged.
This is the rule that trips up schemas ported from an OpenAPI file or a Zod model. The structured output docs call it the one that catches the most integrations.
What does the failing schema look like?
Here subtitle is declared but absent from required. Sume rejects it before any media is generated:
{
"type": "object",
"additionalProperties": false,
"required": ["title"],
"properties": {
"title": { "type": "string" },
"subtitle": { "type": "string" }
}
}How do I write the fixed version?
Add subtitle to required and let its type accept null. The key is then always present in output; null means the run had nothing to put there, which is the case you wanted optional for.
The OpenAI guide says the same thing about its own strict mode: all fields must be required, and an optional field is a union with null. A schema you already wrote for response_format therefore transfers on this point. See OpenAI response_format to Sume output_schema for the rest of the migration.
{
"name": "acme/promo-copy/v1",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["title", "subtitle"],
"properties": {
"title": { "type": "string" },
"subtitle": { "type": ["string", "null"] }
}
}
}Which other rules fail the same create?
The optional-field rule is one of several checks in the same pass. Sume reports every problem at once in details.violations[], each with a path, a stable rule token and a message, so one 400 is enough to fix the whole schema.
| rule | Triggered by | Fix |
|---|---|---|
required_completeness | A declared property missing from required, or a required entry with no property | List every property in required |
additional_properties_false | Any object, nested ones and $defs included, without additionalProperties: false | Add it to every object |
missing_type | A node with no type, $ref or anyOf | Give every node a type |
root_must_be_object | Root type is not exactly object, even ["object","null"] | Wrap arrays in an object |
unsupported_keyword | oneOf, allOf, not, if/then/else, nullable: true | Use anyOf, or a null union |
Does a nullable media field work too?
Yes. A media slot can be a union of SumeMediaFile# and null, written as an anyOf with the $ref in one branch and { "type": "null" } in the other. Remember that $ref and anyOf each short-circuit the node they sit on, so put constraints inside the branches, not beside them.
Making a field nullable also decides whether a half-finished run can report anything. A schema that demands every scene turns a 20-of-40 show into output: null. Nullable fields, and no minItems on arrays you want to receive partially, are what let the ledger through. Pair the loosened schema with primary_output_key so a run that leaves the deliverable empty still ends failed.
What does null mean when I read the result?
Null is the run's own account that it had no value, not a measurement. Values other than URLs and durations are read out of the run's media metadata and closing text, so treat them as the run's report. Also check output_error before reading output: a projection that did not match your schema comes back with output: null and the reason on the receipt.
Sume never fills a missing key with a guess. Identifiers you sent in input, an order id or a SKU, will not appear in output either, because the projection never sees input. Keep those on your side, keyed by the run id or your Idempotency-Key.
What is a quick checklist before I send the schema?
Run through this list and the create is unlikely to return a violation. It is a trimmed version of the checklist at the end of the structured output docs.
- Root is exactly
{"type": "object"}. additionalProperties: falseon every object, including those in$defsand arrayitems.- Every declared property appears in
required; optionality is a nullable union. - No
oneOf,allOf,not,if/then/elseornullable: true. $reftargets are only#/$defs/*declared at the root, andSumeMediaFile#.nameis namespaced and stable, so receipts stay greppable.
Sources
Related posts
More in Formats
- output_schema_unsatisfied with rejected_urls: the Sume URL gate
A Format run that returns output_schema_unsatisfied and rejected_urls named a media URL it did not generate. How the URL gate works and how to fix the schema.
- Format reads inactive but still runs: the 409 codes
A never-run Format may read inactive until its first API run. The real refusal is a 409 format_inactive or format_api_trigger_disabled.
- Format run failed provider_unavailable or mcp_unavailable: retry rules
provider_unavailable and mcp_unavailable are Sume-side Format run failures: retry with a new Idempotency-Key. provider_credits_exhausted waits.
- Format run failed with incomplete_assembly: continue it, do not re-run
incomplete_assembly means a Sume Format run hit its time limit mid-generation. Continue with previous_run_id; finished clips are not regenerated.
Written by Sume