Zurück zu den Leitfäden
Troubleshooting·28. August 2026·6 Min. Lesezeit

“Unsupported parameter: 'max_tokens' is not supported with this model” — use max_completion_tokens

The rename is the easy half. The half that catches people is what the new field counts — max_completion_tokens covers reasoning plus visible output, so a budget sized for the answer alone comes back empty with finish_reason "length", and billed.

Last reviewed on .

The rename is the easy half. The half that catches people is what the new field counts — max_completion_tokens covers reasoning plus visible output, so a budget sized for the answer alone comes back empty with finish_reason "length", and billed.

The error

response (HTTP 400)
{
  "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"
  }
}

Causes and fixes at a glance

CauseFix
Reasoning-model families replaced the fieldSend max_completion_tokens instead of max_tokens on those models.
An SDK or wrapper pinned to the old fieldUpgrade it, or set the field explicitly rather than through the helper.
One code path fanning out to several providersNormalize once at the edge instead of branching per model.
Empty answer after fixing itThe budget includes reasoning tokens — raise it well above your expected output.

Rename the field

At the call site it is a straight substitution. Everything else about the request is unchanged.

fix.py
# Before
resp = client.chat.completions.create(
    model="gpt-5-6-sol", max_tokens=1024, messages=msgs)

# After
resp = client.chat.completions.create(
    model="gpt-5-6-sol", max_completion_tokens=1024, messages=msgs)

Budget for the reasoning you cannot see

max_completion_tokens caps reasoning tokens plus visible output together. If a model spends 900 tokens thinking under a 1,024 cap, you get 124 tokens of answer — or an empty message with finish_reason "length", and a bill for all of it. Size the budget for both, and check finish_reason before trusting an empty response.

Normalize once instead of branching per model

A single helper at the edge of your code keeps the rest provider-agnostic, and stops the next model family from being another round of edits.

normalize.py
def token_budget(model: str, n: int) -> dict:
    """One place that knows which spelling a model wants."""
    if model.startswith("claude-"):
        return {"max_tokens": n}
    return {"max_completion_tokens": n}

resp = client.chat.completions.create(
    model=model, messages=msgs, **token_budget(model, 4096))

Expect the sibling rejections

The same model families that dropped max_tokens often reject temperature and top_p too. Fixing this one usually surfaces the next; remove unsupported sampling parameters rather than setting them to their defaults.

If you’re calling through Kunavo

Kunavo's /v1/chat/completions accepts max_tokens on the GPT-5.x reasoning family: the translator reads whichever of the two spellings you send and maps it onto the upstream field, and /v1/responses does the mirror image. So on those models you do not have to rename anything. One asymmetry stated plainly rather than smoothed over: on claude-* models the chat translator currently reads max_tokens only, so send that spelling for Claude — which is what the helper above does.

FAQ

Is max_completion_tokens just a rename?

At the call site yes, in meaning no — it caps reasoning tokens plus output together, where max_tokens capped visible output only.

Why is my response empty after fixing this?

The budget was spent on reasoning. Check finish_reason: "length" with empty content means raise the cap.

Do I have to branch per model?

Not on Kunavo for the GPT family — both spellings are accepted. Branch only for claude-* models, or use one normalizing helper everywhere.

Related guides

More error semantics live in the error reference; getting a key takes a minute via sign up and the authentication docs.