# LLM returns value 'medium' not in allowed enum ['low', 'high'] when using JSON mode with constrained decoding

- **ID:** `llm/structured-output-enum-violation-in-json-mode`
- **Domain:** llm
- **Category:** data_error
- **Verification:** ai_generated
- **Fix Rate:** 92%

## Root Cause

JSON mode or constrained decoding (e.g., using functions or response_format) does not enforce enum constraints on string values, allowing the LLM to output values outside the specified set.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| openai==1.18.0 | active | — | — |
| anthropic==0.32.0 | active | — | — |
| gpt-4o-2024-05-13 | active | — | — |
| claude-3-haiku-20240307 | active | — | — |
| outlines==0.0.34 | active | — | — |
| lmql==0.4.0 | active | — | — |

## Workarounds

1. **Post-process the LLM output to validate enum values and either reject or map invalid values to a default (e.g., `if value not in ['low', 'high']: value = 'low'`).** (95% success)
   ```
   Post-process the LLM output to validate enum values and either reject or map invalid values to a default (e.g., `if value not in ['low', 'high']: value = 'low'`).
   ```
2. **Use a constrained decoding library like `outlines` or `lmql` that forces the LLM to output only tokens matching the regex or grammar of the enum.** (90% success)
   ```
   Use a constrained decoding library like `outlines` or `lmql` that forces the LLM to output only tokens matching the regex or grammar of the enum.
   ```

## Dead Ends

- **** — Adding more examples to the prompt with correct enum values doesn't guarantee the LLM will follow them, especially for edge cases. (70% fail)
- **** — Using a stricter JSON schema with additionalProperties: false doesn't prevent enum violations because the schema doesn't enforce value constraints at generation time. (85% fail)
- **** — Lowering temperature to 0 doesn't fix enum violations because the model may still sample from improbable tokens. (60% fail)
