OpenAI "Unsupported parameter: 'max_tokens'" (unsupported_parameter): Causes and Fixes
You send a Chat Completions request to a reasoning model and get HTTP 400 telling you max_tokens is not supported and to use max_completion_tokens instead. A close cousin rejects temperature or top_p. Here is what changed, how the three output-cap fields map across APIs, and how to clean up the request.
Quick answer
Reasoning models reject the legacy max_tokens field on Chat Completions — OpenAI deprecated it in favor of max_completion_tokens. Rename the field. On the Responses API the same cap is called max_output_tokens. The related errors for temperature, top_p and logprobs mean those sampling parameters are not accepted at the reasoning effort you are using: remove them. All of these fail at validation time, before the model generates anything.
Symptoms and What the Error Means
The classic body, as reported against OpenAI's own Python SDK:
{
"error": {
"message": "Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.",
"type": "invalid_request_error",
"param": "max_tokens",
"code": "unsupported_parameter"
}
}The sampling-parameter version has the same shape:
{
"error": {
"message": "Unsupported parameter: 'temperature' is not supported with this model.",
"type": "invalid_request_error",
"param": "temperature",
"code": "unsupported_parameter"
}
}Some models accept the parameter name but only its default value, and the message changes accordingly:
Unsupported value: 'temperature' does not support 0 with this model. Only the default (1) value is supported.How to read them:
unsupported_parameter— the field itself is not allowed for this model. Remove or rename it.unsupported_value— the field is allowed, but not with the value you sent. Forreasoning.effortthis is a separate problem; see reasoning effort unsupported value.paramtells you exactly which field to fix. Read it before changing anything else.
Because the request never reached generation, retrying the same body will fail the same way — this is not a transient error.
Why It Happens
max_tokensis deprecated on Chat Completions. OpenAI's API reference marks it deprecated in favor ofmax_completion_tokensand states it is not compatible with o-series models. In practice the GPT-5 family and newer reasoning models reject it the same way, so treat every reasoning model asmax_completion_tokens-only.- The cap now covers reasoning.
max_completion_tokens(Chat Completions) andmax_output_tokens(Responses) both count reasoning tokens as well as visible output. The rename makes that change of meaning explicit. - Sampling controls depend on reasoning effort. OpenAI's GPT-6 migration guidance says to drop
temperature,top_pandtop_logprobswhenever reasoning effort is anything other thannone, pluslogprobson Chat Completions. - Something else is adding the field. SDK wrappers, agent frameworks and CLIs frequently inject
max_tokensor a defaulttemperaturethat you never wrote. OpenAI's own repositories have issues of exactly this kind — a CLI sendingtemperature/top_ptoo3-mini, and an agents library sendingmax_tokensto reasoning models.
The Three Output-Cap Fields at a Glance
| Chat Completions | Responses API | |
|---|---|---|
| Output cap | max_completion_tokens (max_tokens is deprecated) | max_output_tokens (minimum 16) |
| Includes reasoning tokens | Yes | Yes |
| Reasoning effort field | reasoning_effort (top level) | reasoning: { "effort": ... } |
| When the cap is hit | finish_reason: "length" | status: "incomplete", incomplete_details.reason: "max_output_tokens" |
Field names do not carry across: max_completion_tokens belongs to Chat Completions and max_output_tokens to Responses. Some OpenAI-compatible gateways have also been reported to reject max_output_tokens, so if you move between providers, re-test the field name against each endpoint.
Fix 1: Rename max_tokens to max_completion_tokens
The direct fix on Chat Completions:
curl https://byesu.com/v1/chat/completions \
-H "Authorization: Bearer sk-YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-sol",
"messages": [{"role": "user", "content": "Summarize RFC 9110 in three bullets."}],
"max_completion_tokens": 4000
}'With the OpenAI Python SDK:
from openai import OpenAI
client = OpenAI(api_key="sk-YOUR_TOKEN", base_url="https://byesu.com/v1")
resp = client.chat.completions.create(
model="gpt-6-sol",
messages=[{"role": "user", "content": "Summarize RFC 9110 in three bullets."}],
max_completion_tokens=4000, # not max_tokens
)
print(resp.choices[0].finish_reason, resp.choices[0].message.content)If the code also has to serve older non-reasoning models, keep a single internal setting and translate it at the edge rather than sending both fields.
Fix 2: On the Responses API, Use max_output_tokens
If you are already on (or moving to) /v1/responses, the field is different again:
curl https://byesu.com/v1/responses \
-H "Authorization: Bearer sk-YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6.1-sol",
"input": "Summarize RFC 9110 in three bullets.",
"reasoning": {"effort": "low"},
"max_output_tokens": 4000
}'resp = client.responses.create(
model="gpt-6.1-sol",
input="Summarize RFC 9110 in three bullets.",
reasoning={"effort": "low"},
max_output_tokens=4000,
)
if resp.status == "incomplete":
print("Cap reached:", resp.incomplete_details.reason)
else:
print(resp.output_text)The Responses API matters for current models beyond the field name: per OpenAI's model pages, tool calling on gpt-6.1-sol and gpt-6-astra requires Responses, and gpt-6-sol / gpt-6-luna only support function calling on Chat Completions at reasoning_effort: "none".
Fix 3: Strip Sampling Parameters That Don't Apply
Follow OpenAI's GPT-6 migration rule: when reasoning effort is not none, remove temperature, top_p and top_logprobs; on Chat Completions also remove logprobs; on Responses remove message.output_text.logprobs from include.
Which models can run at none (per OpenAI's model pages):
| Model | Accepts reasoning.effort: "none" | Sampling params usable? |
|---|---|---|
gpt-6.1-sol | No | Plan on never sending them |
gpt-6-astra | No | Plan on never sending them |
gpt-6-sol | Yes | Only at effort none |
gpt-6-luna | Yes | Only at effort none |
gpt-5.6-sol | Yes | Assume only at effort none |
A small sanitizer keeps this out of your call sites:
SAMPLING_KEYS = ("temperature", "top_p", "top_logprobs", "logprobs")
def clean_chat_params(params: dict) -> dict:
p = dict(params)
# Legacy cap -> current cap
if "max_tokens" in p:
p.setdefault("max_completion_tokens", p.pop("max_tokens"))
# Sampling controls only make sense at effort "none"
if p.get("reasoning_effort", "medium") != "none":
for k in SAMPLING_KEYS:
p.pop(k, None)
return p
resp = client.chat.completions.create(**clean_chat_params({
"model": "gpt-6-luna",
"messages": [{"role": "user", "content": "ping"}],
"max_tokens": 200,
"temperature": 0.2,
}))The default is treated as medium because both API references document medium as the default effort. The API reference also notes that stop is not supported on o3 and o4-mini, so if you still run those, add stop to the list.
Fix 4: Find the Layer That Adds the Field
If your own code never sets max_tokens or temperature, something in between does. Look at the request as it leaves the process:
# openai-python: log request options, including the JSON body
OPENAI_LOG=debug python your_script.py 2>&1 | grep -i -E "max_tokens|temperature|top_p"Common sources:
- Framework model settings with a default
max_tokensortemperature(agent frameworks, LangChain-style wrappers, eval harnesses). - CLI tools that fill in defaults on every call.
- Client apps with a "max tokens" or "temperature" slider that is always sent, even when untouched.
Fix it where it is injected — usually a model-settings object or a provider config — rather than patching around it per call.
Don't Set the Cap Too Low
Because the cap includes reasoning tokens, a tight max_completion_tokens or max_output_tokens can be consumed entirely by reasoning. OpenAI's reasoning guide warns that the cut-off can happen before any visible output is produced, and suggests reserving at least 25,000 tokens for reasoning and output while you experiment. If you get finish_reason: "length" with an empty message, raise the cap or lower the effort. That is a budget problem, not the context-window error — for that one, see context length exceeded.
If You're Calling GPT Through byesu
byesu is an AI API gateway with an OpenAI-compatible endpoint at https://byesu.com/v1, supporting both Chat Completions and Responses, billed pay-as-you-go with no subscription.
- Same rules, same fields. The parameter guidance above applies unchanged:
max_completion_tokenson/v1/chat/completions,max_output_tokenson/v1/responses, and no sampling parameters at reasoning efforts other thannone. - Exact model IDs. Copy IDs such as
gpt-6.1-solorgpt-6-lunafrom the console model list orGET /v1/modelsso the parameter rules you apply match the model you actually call.
To get set up, follow the Quick Start.
FAQ
What does "Unsupported parameter: 'max_tokens' is not supported with this model" mean?
It is a 400 invalid_request_error with code unsupported_parameter. Reasoning models on Chat Completions do not accept the legacy max_tokens field, which OpenAI has deprecated in favor of max_completion_tokens. Rename the field and the request goes through; the error is raised during validation, before the model generates anything.
What is the difference between max_tokens, max_completion_tokens and max_output_tokens?
max_tokens is the deprecated Chat Completions cap. max_completion_tokens is its replacement on Chat Completions and covers both visible output and reasoning tokens. max_output_tokens is the equivalent cap on the Responses API (minimum 16), and it also includes reasoning tokens.
Why does my reasoning model reject temperature or top_p?
OpenAI's migration guidance for GPT-6 says to remove temperature, top_p and top_logprobs whenever reasoning effort is not none, and to remove logprobs on Chat Completions as well. Models that cannot run at effort none, such as gpt-6.1-sol and gpt-6-astra, should never receive these sampling parameters.
Why does the error appear when I never set max_tokens or temperature?
A library, framework or CLI is adding it for you. SDK wrappers and agent frameworks often inject max_tokens or a default temperature. Log the raw outgoing request body and remove the field at the layer that adds it.
Can I set max_completion_tokens too low on a reasoning model?
Yes. The cap includes reasoning tokens, so a small value can be used up by reasoning before any visible text appears. OpenAI suggests reserving at least 25,000 tokens for reasoning and output when you first experiment with reasoning models.
