Skip to content

Truncation Point Finder

Check an output for the structural signs of a cut — unbalanced JSON, an open code fence, a half-written character — against the finish_reason you were given.

Verdict
1 sign of a cut

These are structural signals from the text alone. Only finish_reason knows the cause — paste it above.

  • okEnds without terminal punctuationThe last character is not something a finished sentence ends on.
  • okUnclosed brackets or bracesAll brackets balanced.
  • okUnterminated string literalA double quote was opened and never closed.
  • okStray closing bracket0 closing bracket(s) with no opener — usually a sign the start was cut, not the end.
  • okUnclosed code fence0 fence marker(s) — an odd number means a block is still open.
  • okEnds mid-characterThe final UTF-16 unit is a lone high surrogate: an emoji or CJK character was cut in half.
  • flagEnds on an incomplete list itemA list marker with nothing after it.
  • okEnds on an incomplete tagAn angle bracket was opened after the last one closed.
  • okEstimated size is at the cap≈ 104 estimated tokens against a cap of 1,024.
Characters
317
Estimated tokens
≈ 104
Share of your max_tokens
10.2%
What this assumes: every check on this page reads the text and nothing else, so it can find evidence that an output was cut and cannot find the cause. Only `finish_reason` knows that, which is why it is an input here rather than an output. The delimiter scan is JSON-aware — quotes and escapes are tracked, so a brace inside a string does not count. The token figure is an estimate, and the “at the cap” check fires at 90% of your max_tokens because the estimate is not exact enough to compare at 100%. Estimated, not tokenized. A real count needs the model's vocabulary; the authoritative number is usage.prompt_tokens on the response.

Why a clean-looking answer can still be truncated

Structural evidence is one-directional. Unbalanced braces mean something went wrong; balanced braces mean nothing at all, because a model that runs out of budget mid-paragraph frequently ends on a full stop. The checks here are worth running because they catch the expensive cases — the JSON your parser will reject, the code block your renderer will swallow the rest of the page into, the emoji cut in half that turns into a replacement character in your database — and because they tell you which one to fix first.

The combination worth knowing is finish_reason: stop with structural damage. That almost always means a stop sequence fired inside legitimate content: the model produced a newline-newline, or the string you set as a delimiter appeared in the answer, and the API cut there and reported a clean stop. It looks identical to a model that decided to end, and it is the one truncation cause people spend a day not finding.

The other common cause is not truncation at all. A response that stops early with a token count nowhere near the cap is usually a model declining, a tool call being emitted instead of content, or a stream that was aborted client-side while the server kept generating and kept billing. Check the cap first because it is cheap; check the transport second, because an aborted stream leaves no trace in the text at all.

Truncation Point Finder · Multigrid