Unsupported types and limitations
On this page
What schemas can’t do
Understanding the limits of structured outputs is just as important as mastering their capabilities. The Grok API doesn’t support certain JSON Schema constraints. Trying to use them will trigger an error or cause unexpected behavior.
The three major restrictions
allOf — composition not allowed
In JSON Schema, the allOf keyword combines multiple subschemas that an object must satisfy simultaneously. The Grok API does not support this feature.
// DOES NOT WORK
{
"allOf": [
{ "properties": { "nom": { "type": "string" } } },
{ "properties": { "age": { "type": "number" } } }
]
}
Alternative: use a single object with all properties:
// WORKS
{
"type": "object",
"properties": {
"nom": { "type": "string" },
"age": { "type": "number" }
}
}
minLength / maxLength — no string length constraints
You can’t force the model to produce a string with a minimum or maximum length.
// DOES NOT WORK
{
"properties": {
"code": {
"type": "string",
"minLength": 3,
"maxLength": 10
}
}
}
Alternative: specify the constraint in the prompt instead of the schema:
messages=[{
"role": "user",
"content": "Generate a product code between 3 and 10 characters."
}]
The model will follow the instruction in most cases, but it isn’t guaranteed like a schema constraint would be.
minItems / maxItems — no array size constraints
You can’t enforce a minimum or maximum number of elements in an array.
// DOES NOT WORK
{
"properties": {
"tags": {
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"maxItems": 5
}
}
}
Alternative: use the prompt to guide the model:
messages=[{
"role": "user",
"content": "List between 1 and 5 relevant tags for this article."
}]
Other limitations to know
No regex patterns
The API doesn’t support pattern constraints on strings. You can’t enforce an email format, UUID, or phone number via the schema.
// DOES NOT WORK
{
"properties": {
"email": {
"type": "string",
"pattern": "^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$"
}
}
}
No default values
The default keyword has no effect. If a field is in the schema, the model will always populate it.
No conditionals
The JSON Schema keywords if, then, and else aren’t available.
The strategy: schema + prompt
The best approach combines both:
- The schema guarantees the structure: field names, types, nesting
- The prompt guides the content: lengths, specific formats, business rules
class Report(BaseModel):
title: str
summary: str
key_points: list[str]
score: float
category: str
messages=[{
"role": "user",
"content": """Analyze this text and produce a report.
- The summary must be 2-3 sentences.
- List exactly 5 key points.
- The score is between 0 and 10.
- Category among: positive, negative, neutral."""
}]
The schema guarantees types and structure. The prompt controls values and content constraints.
Key takeaways
allOf,minLength,maxLength,minItems, andmaxItemsare not supportedpattern,default, andif/then/elseconstraints aren’t supported either- Use
anyOfinstead ofallOfwhen possible - Offload content constraints to the prompt
- Combining schema (structure) + prompt (content) is the optimal strategy