BadRequestError
openai.BadRequestError (HTTP 400: invalid_request_error)
Stack trace
openai.BadRequestError: Error code: 400 - {'error': {'message': 'temperature is not supported for this model', 'type': 'invalid_request_error', 'param': 'temperature', 'code': 'invalid_request_error'}} Why it happens
Reasoning models (o1, o3, o3-mini) use specialized chain-of-thought tokens that require a fixed temperature of 1.0 for valid reasoning trajectory sampling. OpenAI locks temperature to prevent misconfiguration that would degrade reasoning quality. If you pass temperature=0.7 or any value other than the model's internal setting, the API rejects the request with a 400 error before processing.
Detection
Check your model parameter before sending requests: if model.startswith('o1') or model.startswith('o3'), validate that no temperature parameter is included in the API call. Log the model name and detected parameters to catch this during request construction.
Causes & fixes
Copied code from a standard gpt-4o/gpt-4o-mini chatbot that includes temperature parameter, then switched model to o1 without removing temperature
Add conditional logic: if using o1/o3 models, exclude temperature from the request entirely. Use model name detection: `if not model.startswith(('o1', 'o3')): params['temperature'] = 0.7`
Temperature is hardcoded in a configuration file or environment variable that applies to all model types
Refactor config loading to skip temperature for reasoning models: `params = base_params.copy(); if not is_reasoning_model(model): params['temperature'] = config['temperature']`
Using a wrapper function or SDK helper that always injects temperature=0.7 without checking model type
Modify the wrapper to accept model name as a parameter and conditionally include temperature: `def call_llm(model, messages, temp=0.7): kwargs = {'model': model, 'messages': messages}; if not model.startswith(('o1', 'o3')): kwargs['temperature'] = temp; return client.chat.completions.create(**kwargs)`
Using deprecated SDK v0 code that had different parameter validation, then upgraded to SDK v1 with o1/o3 models
Upgrade to OpenAI SDK v1.3+, remove all deprecated temperature handling, and use the new strict parameter validation: `from openai import OpenAI; client.chat.completions.create(model='o3-mini', messages=messages)` with no temperature key
Code: broken vs fixed
from openai import OpenAI
import os
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))
# This code will fail with 400 BadRequestError — temperature is not supported for o1/o3
response = client.chat.completions.create(
model='o3-mini',
messages=[{'role': 'user', 'content': 'Solve: 2x + 5 = 13'}],
temperature=0.7 # ❌ BREAKS: o3-mini does not accept temperature
)
print(response.choices[0].message.content) from openai import OpenAI
import os
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))
# Fixed: temperature removed for o3-mini (reasoning model)
response = client.chat.completions.create(
model='o3-mini',
messages=[{'role': 'user', 'content': 'Solve: 2x + 5 = 13'}]
# ✅ FIXED: No temperature parameter for reasoning models
)
print(response.choices[0].message.content) Workaround
If you have a multi-model codebase that must support both standard and reasoning models, create a helper function that conditionally includes temperature: `def build_params(model, base_temp=0.7): params = {'model': model}; if not any(m in model for m in ['o1', 'o3']): params['temperature'] = base_temp; return params`. Call this before `client.chat.completions.create(**params)` to avoid 400 errors on reasoning models while maintaining temperature control for gpt-4o-mini and other standard models.
Prevention
Establish a request builder pattern that validates model type before adding parameters: separate 'reasoning_model_params' from 'standard_model_params' configurations, and load the correct set based on model name detection. Add unit tests that verify o1/o3 requests never include temperature, and standard models always do. Document in your LLM selection guide that o1/o3 models have temperature=1.0 fixed and cannot be overridden.