Short answer
This is not an API failure — it is the thinking budget eating the output budget. Reasoning models such asgpt-6.1-sol first generate a reasoning trace, then write the answer. Both parts share the max_tokens allowance. When the budget runs out during thinking, the answer is cut off before it starts, so you receive an empty result.
Raise max_tokens (1000 or more is a safe start), or lower the reasoning effort, and the problem disappears.
What you will see
There are two common forms. One is an explicit error, with HTTP status 429 or 500 (themessage field may be localized, so a Chinese message is expected on some responses):
completion_tokens is 300, reasoning_tokens is 300, text_tokens is 0 — the model generated 300 tokens, spent all of them thinking, and never wrote a single word of output.
The call log shows the request as successful and billed, which is not a contradiction: the model did produce content (the reasoning trace), just no visible text.
Why this happens
A reasoning model’s output has two stages:max_tokens (or max_completion_tokens, max_output_tokens) limits both stages combined, not the length of the visible answer.
So if max_tokens is set to something small like 200–500 while the task needs substantial reasoning, the budget is exhausted during thinking. finish_reason becomes length and the content is empty.
Three checks
1
Step 1: read finish_reason
If it is
length, the output was truncated — the model did not refuse to answer. If it is stop but the content is still empty, continue to steps 2 and 3.2
Step 2: read reasoning_tokens in usage
Find
usage.completion_tokens_details.reasoning_tokens and compare it with completion_tokens. If the two are close or equal, most of the budget went into thinking.3
Step 3: read max_tokens in your request
If you explicitly set
max_tokens to a small value (300, for example), that is almost certainly the cause. If you did not set it, check whether your SDK or framework filled in a small default.How to fix it
Raise max_tokens
The direct fix. Use 1000–2000 for ordinary chat and 4000 or more for heavy reasoning or long-form output. Reasoning overhead can be much larger than you expect.
Lower reasoning effort
If the model supports
reasoning_effort, drop it from high to medium or low. Thinking consumption falls noticeably.Switch to streaming
Set
stream to true. The reasoning trace arrives as separate events, so you can see what the model is doing and the answer never silently disappears.Parameter reference by model family
FAQ
Why does the log show success while I received an error?
Why does the log show success while I received an error?
The log records that the upstream finished generating and settled billing. It does not check whether the visible text is empty. Generation succeeding and the answer being non-empty are two different things.
Will simply retrying help?
Will simply retrying help?
Usually not. With the same prompt and the same
max_tokens, the model will most likely spend the budget on thinking again. Changing the parameters is far more effective than retrying.Am I billed for an empty response?
Am I billed for an empty response?
Yes. Reasoning tokens are real consumption and are billed as output tokens. Check call logs for the exact amount.
Does every model behave this way?
Does every model behave this way?
No. Only reasoning models with a thinking stage have this problem. Ordinary non-reasoning models such as
gpt-4o or deepseek-chat spend the whole max_tokens on visible output.Does a large max_tokens cost more?
Does a large max_tokens cost more?
No.
max_tokens is a ceiling, not actual consumption. The model stops when it finishes, and you pay for the tokens actually generated.Related
What is max_tokens?
Parameter meaning, naming history, and per-model defaults
Streaming vs non-streaming
Prefer streaming for long responses and reasoning models
How to troubleshoot model errors
General triage for 400, 401, 429, and 503
How to read billing in logs
Confirm whether a request was billed, and how much