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.

5 min readSume
All posts

output_schema_unsatisfied with details.rejected_urls[] means the structured output named a media URL that this run did not generate, so Sume refused to return it. The gate compares every URL in output against the media the run really produced, by exact string equality. The fix is usually in your schema or instruction, not in a retry.

The check is the reason a completed Format run "never returns a schema-shaped guess", as the structured output docs put it.

What exactly does the URL gate check?

Before a custom output reaches you, two passes run. The first collects every http(s):// string anywhere in the object, at any depth, whether or not you declared the field as media. The second collects the url of every SumeMediaFile-shaped value whatever it contains, so a placeholder such as "none" or an empty string cannot slip past by not looking like a URL.

A URL that was not produced by the run fails the projection, even a plausible media.sume.com one. Then the object is validated against your schema.

Why does my run trip it?

Four causes cover most cases.

  • Your schema requires a file the Format never makes, for example two images when the recipe produces one. Compare details.harvested, a count by media type, with the fields you require.
  • A field holds a file the run merely uploaded. The gate admits only media the run generated, so an uploaded URL fails the projection and takes the whole output with it. Keep uploads out of your schema.
  • A whole made of parts, such as scenes, reuses one scene's file as the assembled video. The check needs two or more parts reporting succeeded with their own video, and a video outside every part reusing one of those files.
  • A duration_ms in a media object disagrees with the ledger by more than 10 percent. Where no length was recorded, nothing is checked.

What does the failed receipt look like?

Over the API a projection failure is a run failure: status is failed, output is null, and error repeats output_error. The artifacts[] list still holds everything the run made, so you can show the media and log the shape failure. details.rejected_urls[] lists the first 10 only.

{
  "status": "failed",
  "output": null,
  "output_error": {
    "code": "output_schema_unsatisfied",
    "details": {
      "rejected_urls": ["https://media.sume.com/artifacts/artf_fake/image.png"],
      "harvested": { "images": 1, "videos": 0, "audio": 0, "files": 0 }
    }
  },
  "primary_output_url": null
}

How do I fix it?

Work from the receipt, not from the schema in your head.

Triage for output_schema_unsatisfied, from the Errors and spend docs (read 2026-10-02).
Symptom in detailsLikely causeChange
rejected_urls[] present, harvested lower than requiredSchema demands media the Format does not makeMake the field a nullable union, or change the instruction
violations[] presentShape mismatch, not mediaFix each named path
Repeats on every run of one FormatStructural schema/recipe mismatchReread the Format with GET /v1/formats/{handle}/{slug} and its io profile

Should I retry the run?

Not blindly. A retry re-spends generation if it makes media again. If the media exists in artifacts[] and a part is only missing from the shape, continue the run with previous_run_id and the same output_schema, since the schema is per run and not inherited. A fresh attempt needs a new Idempotency-Key, because the old one is bound to the receipt you already hold.

Sume does not publish a way to let the gate accept an arbitrary URL. If you need your own files in a result, store them against the run id on your side.

What does the gate not check?

The gate guards URLs, durations and shape. Every other value, such as ids, labels, captions and counts, is read from the run's media metadata and closing text, so it is grounded in what the run reported rather than verified against it. Treat those fields as the run's own account of its work. A duration_seconds number you declared yourself is written by the projection; the duration_ms on the media file is the checked one.

The built-in schema avoids all of this. Bind nothing and output is filled deterministically from the run's generated media and final text, with no model involved, so it cannot fail the way a custom schema can.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume