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 output rejects an uploaded file's URL: generated media only
The Sume output URL gate admits only media the run generated. An uploaded file's URL in your schema fails the projection and takes all of output.
Written by Sume