Skip to content

cluster: reasoning turns end in finish_reason=length with empty content and no usage block (~60k chars ceiling on deepseek-v4-flash, glm5.3-flash, qwen3.8-flash) #90

Description

@dakotad74

Summary

On reasoning-heavy requests, the cluster's OpenAI-compatible endpoint returns a turn that ends with finish_reason: "length", empty content, and no usage object, even when max_tokens: 384000 is requested and the reasoning trace stops at ~59,994 characters — well below the requested budget. The cut happens at roughly the same point on every attempt, so the caller receives a truncated turn with no answer and no accounting.

Reported by a member; every figure below is measured from the client side against https://api.nan.builders/v1, and is reproducible with no client in the middle.

Impact

  • A truncated turn is indistinguishable from a completed one for anything that reads finish_reason without a usage block: agents treat a dead end as an answer.
  • Token accounting breaks: with stream_options.include_usage set and no usage chunk emitted, the caller cannot price or cap the attempt.
  • Each reproduction costs a long reasoning generation and returns nothing, so this is expensive to investigate from the member side — it consumed a full morning of bisecting and a large amount of budget.

Reproduction (direct, no client)

POST https://api.nan.builders/v1/chat/completions

Authorization: Bearer ***
Content-Type: application/json
User-Agent: opencode/1.18.31

Body:

{
  "model": "deepseek-v4-flash",
  "max_tokens": 384000,
  "stream": true,
  "stream_options": { "include_usage": true },
  "messages": [
    {
      "role": "user",
      "content": "OUTPUT BUDGET CALIBRATION RUN. Produce at least 500 distinct numbered findings about robustness, error handling, and edge cases in a Binance websocket/REST connector, each finding at least 100 words. Do NOT summarize or shorten. Do NOT stop early. Completeness is the only success criterion. End with a JSON line: {\"calibration\":true,\"findings_count\":<n>}"
    }
  ]
}

Note on the proxy: requests without a User-Agent are rejected with 403 "error code: 1010", so the reproduction above carries one.

Observed

finish_reason: "length"
reasoning_content: ~59,994 chars
content: (empty)
usage: (absent — no usage chunk even with include_usage: true)

The ceiling reproduces across three models from OpenCode sessions, landing in the same ~60k-character window every time:

model reasoning_content chars
deepseek-v4-flash 59,991 – 59,999
qwen3.8-flash 59,996 – 59,997
glm5.3-flash 59,994

Controls that complete normally

Same endpoint, same max_tokens: 384000:

prompt completion tokens finish_reason
integer-list prompt 93,429 stop
review-shaped prompt with tools 38,222 stop

So this is not a blanket output cap: a run of 93,429 completion tokens finishes normally. The failure looks prompt-shaped — it triggers on certain long reasoning generations rather than at a fixed token count — and when it triggers, the turn is cut without a usage block.

What this rules out

  • Not a client bug. It reproduces with curl directly, no client involved.
  • Not a context-window limit. The prompt is short and the requested budget is far above where generation stops.
  • Not a global output cap. The integer-list control returns 93,429 completion tokens.
  • Not one model. Three different models show the same ~60k-character ceiling.

Related

Questions

  1. Is there an undeclared reasoning/output budget (~32k reasoning tokens) on deepseek-v4-flash, glm5.3-flash and qwen3.8-flash?
  2. Why is usage omitted when a turn is cut with finish_reason=length? Clients such as OpenCode and the gentle-ai review agents need it to tell "done" apart from "truncated" and to account spend.
  3. Can the ceiling be raised or removed, or is it a model limit members should design around — in which case, should it be published alongside the per-model limits already documented?

Environment

  • Endpoint: https://api.nan.builders/v1/chat/completions
  • Models: deepseek-v4-flash, glm5.3-flash, qwen3.8-flash
  • Clients that show it: OpenCode 1.18.31, gentle-ai review agents
  • Reproduced: 2026-09-17, from the EU, member API key

I can provide the full raw SSE stream of a failing run, or run any specific test you need — the reproduction above is self-contained.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions