Format output_schema nullable: true is rejected, use a type union
OpenAPI nullable: true fails a Sume output_schema as unsupported_keyword. Declare optional fields as type [string, null] and keep them in required.

If you paste an OpenAPI schema into a Sume Format run's output_schema, nullable: true fails the create with 400 output_schema_invalid, because the keyword is not on the allowlist and the violation rule is unsupported_keyword. Write a nullable union instead: "type": ["string", "null"], and keep the property in required.
Sume's Structured output page lists the accepted keywords exactly and says anything else is a violation, not something quietly ignored. Its stated reason: an ignored constraint would be a schema Sume could not promise to meet.
Why is nullable: true refused instead of ignored?
OpenAPI 3.0 uses nullable: true; JSON Schema expresses the same idea with a null type. Sume works from an allowlist of keywords, and nullable is not on it. The docs' table of rejected keywords names it directly and gives the replacement: a nullable union.
OpenAI's Structured model outputs page, read 2026-10-03, describes the same convention: optional properties use null union types such as "type": ["string", "null"] rather than omission.
What replaces it?
Move the null into the type and leave the field in required. Sume has no optional property, so null is how a run says it had nothing to put there.
| You wrote | Result | Write instead |
|---|---|---|
"type": "string", "nullable": true | unsupported_keyword | "type": ["string", "null"] |
Property declared, left out of required | required_completeness | Add it to required, make it a null union |
"strict": false | Accepted, changes nothing | Fix the schema; there is no escape hatch |
"subtitle": { "type": ["string", "null"] }
// and at the object level
"required": ["title", "subtitle"]How do I read a nullable field in my code?
Treat null as "the run had nothing here", not as an error. The field is always present, so run.output.subtitle is either a string or null, and you never need a has_key branch.
The same habit makes partial results legal. The docs' ledger example makes the assembled full_video nullable and pairs it with primary_output_key, so a run that fills the scene list but not the final cut still ends failed with primary_output_missing instead of a quiet success.
What should I check before sending?
Run this short list against any schema ported from OpenAPI before you send it to a Format.
- Search your schema for
nullable,oneOf,allOf,patternPropertiesandif. All are rejected. - Every object, including those inside array
itemsand$defs, hasadditionalProperties: false. - Every declared property is listed in
required. - Read
details.violations[]from the400: every problem comes back at once, so one request is enough to fix the schema. - A rejected schema costs nothing, because the call fails before a run exists.
What does the violation look like?
The 400 carries error.code output_schema_invalid and details.violations[]. Each entry is { path, rule, message }, where path points at the offending node, for example #/properties/subtitle, and rule is unsupported_keyword. Switch on rule; the message text may change.
If the same schema also declares subtitle without listing it in required, you will see a second violation with the rule required_completeness in the same response. Every problem is reported at once, so one request is enough to see the whole list.
A null does not change the bill. Null is just a value in the projection. What the run is billed for is metered generation, not the shape of your JSON, and the docs describe usage.billable_amount_usd_micros as generation spend attributed to the run.
What null does change is your branching. A null on a media field means the run did not make that file, and the URL gate guarantees that any non-null URL in output is one this run actually produced. That is why a nullable media field is the documented way to keep a partial result legal.
Sources
Related posts
More in Formats
- Format output_schema: $ref "#" fails, a $defs self-reference works
Sume rejects root recursion via $ref "#" in output_schema as unsupported_ref but accepts a $defs entry that references itself. How to write a tree.
- Format output_schema root must be an object: wrap an array root
A Sume Format run rejects an output_schema whose root is an array or type union with 400 and rule root_must_be_object. Wrap it in a named key.
- Format output_schema strict false: no loose JSON mode on Sume
Sending strict: false with a Sume Format output_schema is accepted but relaxes nothing, and there is no json_object mode. Bind a schema or use the built-in.
- Format run media URLs are public: copy on webhook or proxy
Sume Format run media lives at durable public media.sume.com URLs. If customer A must not see customer B's video, copy it at receipt time or proxy it.
Written by Sume