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.

5 min readSume
All posts

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.

Violation rules that commonly appear next to a missing required entry, per the structured output docs (read 2026-10-02).
ruleTriggered byFix
required_completenessA declared property missing from required, or a required entry with no propertyList every property in required
additional_properties_falseAny object, nested ones and $defs included, without additionalProperties: falseAdd it to every object
missing_typeA node with no type, $ref or anyOfGive every node a type
root_must_be_objectRoot type is not exactly object, even ["object","null"]Wrap arrays in an object
unsupported_keywordoneOf, allOf, not, if/then/else, nullable: trueUse 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: false on every object, including those in $defs and array items.
  • Every declared property appears in required; optionality is a nullable union.
  • No oneOf, allOf, not, if/then/else or nullable: true.
  • $ref targets are only #/$defs/* declared at the root, and SumeMediaFile#.
  • name is namespaced and stable, so receipts stay greppable.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume