High severity HTTP 400 beginner · Fix: 2-5 min

BadRequestError

openai.BadRequestError (HTTP 400)

What this error means
OpenAI o3-mini's reasoning_effort parameter received an invalid value; only 'low', 'medium', and 'high' are accepted.

Stack trace

traceback
openai.BadRequestError: Error code: 400 - {'error': {'message': "Invalid value for 'reasoning_effort': must be one of 'low', 'medium', 'high'", 'type': 'invalid_request_error', 'param': 'reasoning_effort'}}
QUICK FIX
Replace your reasoning_effort value with one of: 'low', 'medium', or 'high': use .lower().strip() if reading from environment variables.

Why it happens

The o3-mini reasoning model requires the reasoning_effort parameter to control inference cost and latency tradeoffs. Only three discrete values ('low', 'medium', 'high') are valid; passing strings like 'minimal', 'balanced', 'maximum', or numeric values triggers a 400 Bad Request error from OpenAI's validation layer.

Detection

Log all reasoning_effort values in your model calls and validate against the set {'low', 'medium', 'high'} before sending to OpenAI. Use type hints (Literal['low', 'medium', 'high']) to catch invalid values at development time.

Causes & fixes

1

Using an unsupported string value like 'minimal', 'balanced', 'maximum', or 'extreme' instead of the three valid values

✓ Fix

Replace with one of the three supported values: 'low' (fastest, cheapest), 'medium' (balanced), or 'high' (most thorough reasoning). Example: reasoning_effort='medium'

2

Passing a numeric value (1, 2, 3) or None instead of a string

✓ Fix

Ensure reasoning_effort is always a string: 'low', 'medium', or 'high'. If using a variable, wrap it with str() or validate its type before the API call.

3

Using an environment variable or config that contains whitespace or case variation (e.g., 'Low', ' medium ', 'LOW')

✓ Fix

Normalize the value: use .lower().strip() on the input before passing to OpenAI. Example: reasoning_effort = os.getenv('REASONING_EFFORT', 'medium').lower().strip()

4

Omitting reasoning_effort or passing it for models that don't support it (gpt-4o, gpt-4o-mini)

✓ Fix

Only set reasoning_effort for o-series reasoning models (o3, o3-mini, o1). Remove it from non-reasoning model calls or conditionally include it only when model name contains 'o3' or 'o1'.

Code: broken vs fixed

Broken - triggers the error
python
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))

# BROKEN: invalid reasoning_effort value
response = client.chat.completions.create(
    model='o3-mini',
    messages=[{'role': 'user', 'content': 'Solve: 2+2'}],
    reasoning_effort='maximum'  # ❌ INVALID — only 'low', 'medium', 'high' allowed
)
print(response.choices[0].message.content)
Fixed - works correctly
python
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))

# FIXED: use valid reasoning_effort value and normalize from env
reasoning_effort = os.environ.get('REASONING_EFFORT', 'medium').lower().strip()

if reasoning_effort not in ['low', 'medium', 'high']:
    raise ValueError(f"reasoning_effort must be 'low', 'medium', or 'high', got {reasoning_effort}")

response = client.chat.completions.create(
    model='o3-mini',
    messages=[{'role': 'user', 'content': 'Solve: 2+2'}],
    reasoning_effort=reasoning_effort  # ✅ Valid value: 'low', 'medium', or 'high'
)
print(response.choices[0].message.content)
Added validation to ensure reasoning_effort is one of the three valid strings ('low', 'medium', 'high'), normalized input with .lower().strip() to handle environment variables safely, and added a guard clause to fail fast with a clear error before hitting the OpenAI API.

Workaround

If you must support multiple reasoning effort levels in a config system that uses different naming, create a mapping dictionary: effort_map = {'minimal': 'low', 'balanced': 'medium', 'maximum': 'high', 'extreme': 'high'} and translate the config value before passing to OpenAI.

Prevention

Use Python Literal type hints in your function signatures: from typing import Literal; def call_o3(effort: Literal['low', 'medium', 'high']) -> ... to catch invalid values at development time with mypy. For config-driven systems, validate against a whitelist before any API call.

Python 3.9+ · openai >=1.0.0 · tested on 1.55.0+
Verified 2026-04 · o3-mini, o3, o1
Verify ↗

Community Notes

No notes yetBe the first to share a version-specific fix or tip.