Skip to main content

Short answer

This is not an API failure — it is the thinking budget eating the output budget. Reasoning models such as gpt-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 (the message field may be localized, so a Chinese message is expected on some responses):
The other is HTTP 200 with empty content:
Look at the usage block: 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.
This script prints all three signals at once:

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

Some reasoning models reject max_tokens and require max_completion_tokens. A wrong parameter name may raise an error, or may be silently ignored so the model falls back to a default that does not match your intent.

FAQ

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.
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.
Yes. Reasoning tokens are real consumption and are billed as output tokens. Check call logs for the exact amount.
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.
No. max_tokens is a ceiling, not actual consumption. The model stops when it finishes, and you pay for the tokens actually generated.

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