Gemini Controlled Generation response_schema Error — Fix (2026) | AI Error Hub
GeminiStructured OutputsSeverity: MediumHTTP 400

Gemini Controlled Generation (response_schema) Error

You're using response_mime_type + response_schema to force JSON output but hitting schema errors. Gemini's controlled generation shares constraints with function calling (OpenAPI 3.0 subset). Fix by using supported types, uppercase type names, and property_ordering for stable field order.

Error code: INVALID_ARGUMENTHTTP: 400Category: Structured OutputsLast tested: Nov 15, 2026
Quick Fix (TL;DR)

Set response_mime_type="application/json" AND provide response_schema — both together for guaranteed JSON matching schema. Or use response_mime_type="text/x.enum" + enum schema for single-value classification. Types must be uppercase. Use property_ordering for consistent output. Gemini's Pydantic → Schema helper handles most translation.

The Error Messages You're Seeing

Response body variants
HTTP/1.1 400 Bad Request

{
  "error": {
    "code": 400,
    "message": "response_schema requires response_mime_type to 
    be application/json or text/x.enum.",
    "status": "INVALID_ARGUMENT"
  }
}

Variants:
"Invalid response_schema: field 'age.minimum' not supported"
"response_schema type must be OBJECT for JSON mode"
"text/x.enum requires schema type STRING with enum values"
"response_json_schema is deprecated; use response_schema"
"Cannot use both response_schema and tools in the same request"

response_mime_type Modes

MIME typeSchema neededUse case
application/jsonOBJECT or ARRAY schemaStructured data extraction
text/x.enumSTRING with enumClassification (single value)
text/plain (default)NoneFree text

What Actually Causes This Error

32%
Missing response_mime_typeSchema set but MIME type still text/plain — model ignores schema.
22%
Unsupported OpenAPI features in schemaSame restrictions as function calling: no oneOf, unsupported formats.
18%
Combining response_schema + toolsMutually exclusive in single request.
15%
Wrong schema type for MIMEARRAY schema with text/x.enum errors; enum needs STRING type.
8%
Deprecated response_json_schema fieldOld code using pre-GA field name.
5%
Inconsistent field ordering causes parsing issuesDifferent runs produce different orderings; no property_ordering.

Fixes That Work (Tested Nov 2026)

1JSON Mode with Schema

Python · controlled JSON output
from google import genai from google.genai import types import json client = genai.Client() response = client.models.generate_content( model="gemini-2.5-flash", contents="iPhone 17 Pro, 256GB, Titanium, $1299", config=types.GenerateContentConfig( response_mime_type="application/json", response_schema=types.Schema( type="OBJECT", properties={ "name": types.Schema(type="STRING"), "storage_gb": types.Schema(type="INTEGER"), "color": types.Schema(type="STRING"), "price_usd": types.Schema(type="NUMBER") }, required=["name", "storage_gb", "color", "price_usd"], property_ordering=["name", "storage_gb", "color", "price_usd"] ) ) ) # Response text is guaranteed valid JSON matching schema data = json.loads(response.text) # {"name": "iPhone 17 Pro", "storage_gb": 256, ...}

2Enum Classification Mode

Python · text/x.enum for classification
# Single-value classification — cheaper and faster than JSON mode response = client.models.generate_content( model="gemini-2.5-flash-lite", contents="Classify this ticket: 'My subscription won't renew'", config=types.GenerateContentConfig( response_mime_type="text/x.enum", response_schema=types.Schema( type="STRING", enum=["billing", "technical", "account", "other"] ) ) ) # response.text is exactly one enum value, guaranteed category = response.text # "billing" assert category in {"billing", "technical", "account", "other"} # For multi-label, use JSON mode with array-of-enums schema multi_response = client.models.generate_content( model="gemini-2.5-flash-lite", contents="Tags for: 'Slack outage affects billing team login'", config=types.GenerateContentConfig( response_mime_type="application/json", response_schema=types.Schema( type="ARRAY", items=types.Schema( type="STRING", enum=["outage", "auth", "billing", "integration"] ) ) ) ) tags = json.loads(multi_response.text) # ["outage", "auth", "billing"]
Enum mode is faster and cheaper

text/x.enum bypasses full JSON generation — model emits a single token from the enum set. Ideal for classification, routing, sentiment. On Flash-Lite this can be 5-10× cheaper per call than JSON mode.

3Pydantic Integration

Python · Pydantic model as schema
from pydantic import BaseModel from typing import Optional, Literal from google import genai from google.genai import types class Product(BaseModel): name: str storage_gb: int color: str price_usd: float category: Literal["phone", "tablet", "laptop"] # google-genai SDK accepts Pydantic types directly as response_schema response = client.models.generate_content( model="gemini-2.5-flash", contents="iPhone 17 Pro, 256GB, Titanium, $1299", config=types.GenerateContentConfig( response_mime_type="application/json", response_schema=Product # ← Pydantic type directly ) ) # Auto-parsed by SDK product = response.parsed # Product instance print(product.name, product.price_usd) # For List[Product]: from typing import List response = client.models.generate_content( model="gemini-2.5-flash", contents="List 3 recent iPhones with specs", config=types.GenerateContentConfig( response_mime_type="application/json", response_schema=list[Product] # typing supported ) ) products = response.parsed # List[Product]

Preventing This Error Going Forward

  • Always pair response_mime_type + response_schema. Neither alone enforces both.
  • Uppercase types in raw dict schemas. STRING, OBJECT, INTEGER.
  • Use property_ordering for consistent parsing. Especially for arrays.
  • Don't combine tools + response_schema. Choose one per request.
  • Prefer Pydantic for maintainability. SDK handles most translation.
  • Use text/x.enum for single-label tasks. Faster, cheaper.
  • Validate response.parsed exists before using. Falls back to text on schema mismatch.
AR
Tested by Ahmed R.
Researcher · AI Error Hub
Last verified: Nov 15, 2026 · SDK: google-genai 0.8+

Frequently Asked Questions

Not in the same request. Choose: response_schema forces the model's final output shape, tools let the model call functions. If you need both patterns, do multi-turn: tools for gathering data, then a final call with response_schema for structured summary.

No — same token pricing. There's minor pre-compilation overhead on new schemas (~100-500ms first call) then cached. Overall usually FASTER because the model doesn't waste tokens on preamble/markdown.

Rare with controlled generation but can happen on very complex schemas or edge cases. Wrap json.loads in try/except; on failure, retry with same prompt (schema compilation improves consistency).

Only if you passed a Pydantic/dataclass as response_schema. With raw types.Schema, use response.text and parse manually. Check for None before accessing.

Yes but keep reasonable (5-6 levels max). Deeply nested schemas hurt accuracy and can hit token overhead limits. Consider flattening or using multi-step calls for complex hierarchies.