Even with careful prompting or structured generation, production systems should validate LLM output against the expected schema before using it — treating the model's output as untrusted input to your own system, not a guaranteed-correct value.
Basic Validation Example
from jsonschema import validate, ValidationError
schema = {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"status": {"type": "string", "enum": ["pending", "shipped", "delivered"]},
"total": {"type": "number"}
},
"required": ["order_id", "status", "total"]
}
def get_validated_response(raw_json_string):
try:
data = json.loads(raw_json_string)
validate(instance=data, schema=schema)
return data
except (json.JSONDecodeError, ValidationError) as e:
log_warning(f"Invalid LLM output: {e}")
return None # caller must handle this explicitly
Two distinct failure modes are worth catching separately: invalid JSON syntax (json.JSONDecodeError) and valid JSON that doesn't match your schema (ValidationError, e.g. a missing required field or wrong type).
What to Do When Validation Fails
| Strategy | When to Use |
|---|---|
| Retry the same request | Occasional, non-systematic failures — often succeeds on a second attempt |
| Retry with a "repair" prompt showing the invalid output and asking for a fix | When you want to salvage a close-but-invalid response rather than regenerate from scratch |
| Fall back to a default/safe response | When repeated failures occur and blocking the user isn't acceptable |
| Escalate to human review | High-stakes outputs where an incorrect guess is worse than a delay |
Why This Step Is Not Optional
Skipping validation means any structural drift in model output — a missing field, an unexpected type, a value outside the expected enum — flows directly into your application logic, potentially causing a crash, silent data corruption, or an incorrect action taken automatically. Validation is the boundary that catches this before it propagates.
Practical Use Case
Any pipeline where LLM output feeds directly into automated downstream logic (updating a database, triggering a workflow, calling another API) needs validation as a hard gate — this is standard defensive engineering, applied to a new kind of untrusted input source.
Common Mistakes
- Trusting LLM output structure implicitly because "it usually works," without a validation step catching the cases where it doesn't
- Treating "valid JSON" and "matches my expected schema" as the same check — valid JSON can still have the wrong fields or types
- Crashing the whole request pipeline on a validation failure instead of a graceful, handled fallback path
Interview Relevance
"Should you trust an LLM's structured output without validation, even with a well-designed prompt?" — no; a strong answer treats LLM output as untrusted input needing the same validation discipline as any external data source.
Practice Question
Design the validation and fallback logic for a feature that extracts a shipping address from customer text — what happens if a required field is missing?