Why valid Draft-07 JSON Schemas still fail with HTTP 400 on LLM APIs
Constrained-decoding engines compile your JSON Schema into a context-free grammar or finite-state token mask before generation starts. To keep grammar compilation fast and bounded, OpenAI, Anthropic, and Google each enforce a stricter subset of JSON Schema than standard Ajv, Zod, or Pydantic exporters emit by default.
For example, OpenAI's strict: true mode rejects any object node that omits additionalProperties: false OR leaves a property out of the required array—meaning optional fields must be represented as nullable unions (["string", "null"]) while still appearing in required. Conversely, Google Gemini's generationConfig.responseSchema rejects the additionalProperties keyword altogether.
| Schema rule | OpenAI Strict (strict: true) | Anthropic Strict Tool / JSON | Gemini responseSchema |
|---|---|---|---|
| Root type must be "object" | Required | Required | Recommended |
| "additionalProperties": false on every object | Required (400 if omitted) | Required (400 if omitted) | Rejected (400 if present) |
| All properties listed in "required" | Required (use [type, "null"] for optional) | Optional keys allowed | Optional keys allowed |
| Regex pattern / minLength / format | Unsupported in strict grammar | Limited; prefer description + app check | Unsupported on most string formats |