Back to blog

AI for beginnersGuide

Why does an AI answer stop mid-sentence? max_tokens, the context window and finish_reason explained

An AI answer that stops mid-sentence hit a limit. Read finish_reason, tell max_tokens from a full context window and check each model’s output limit.

By CheapTokens TeamPublished Updated 7 min read

Dark cover with the cheaptokens logo: the words max_tokens, finish_reason and length in boxes, and the headline “Answer cut off mid-sentence?”
On this page
  1. Three limits that cut an answer
  2. Read finish_reason first
  3. Fix 1: raise max_tokens
  4. Fix 2: when the context window is full
  5. Fix 3: get a long answer in parts
  6. When finish_reason is stop
  7. Picking a model by answer length

A reply that stops in the middle of a sentence was almost always cut off by a limit. The model didn't lose its train of thought; the request ran out of room. The response says which limit it was: read finish_reason. length means a limit was hit. stop means the model finished on its own.

Three things decide how long an answer can be. Once you know which one bit you, the fix takes a minute.

Three limits that cut an answer#

  • max_tokens is a cap you set in the request. When the answer reaches it, generation stops, even mid-word. DeepSeek's API reference defines it as the maximum number of tokens generated in the completion.
  • The model's output limit is the ceiling for a single answer from that model. It belongs to the model, so keep max_tokens at or below it. The numbers for our models are in the table below.
  • The context window is the room for the whole exchange: your input and the answer together. DeepSeek's reference says the input and generated tokens together are capped by the model's context length.

If tokens are still a fuzzy idea, start with What is a token in AI?. This page assumes you know what one is.

Read finish_reason first#

Every choice in a chat response carries a finish_reason. Next to it, usage tells you how many tokens went in and out.

Here is what a cut-off answer looks like next to a finished one. The request asked "In one short sentence, what is a token?", first with max_tokens set to 16, then with 200.

Illustrative example, not a recorded response: your counts and extra fields will differ.

json
{
  "choices": [
    {
      "message": { "role": "assistant", "content": "A token is a small piece of text that a model reads and writes, usu" },
      "finish_reason": "length"
    }
  ],
  "usage": { "prompt_tokens": 21, "completion_tokens": 16, "total_tokens": 37 }
}
json
{
  "choices": [
    {
      "message": { "role": "assistant", "content": "A token is a small piece of text that a model reads and writes, usually a word or part of a word." },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 21, "completion_tokens": 24, "total_tokens": 45 }
}

In the first response completion_tokens is 16, exactly the cap, and the text ends in "usu". In the second the model stopped at 24 tokens, well under the cap of 200, because it was done.

To work out what happened, go through this in order:

  1. Look at finish_reason. If it's stop, the answer is complete. The model chose to end, or hit a stop sequence you set. If it's length, a limit cut the answer off, and the next step tells you which one. Other values exist, such as content_filter and tool_calls; neither is a length problem.
  2. Compare completion_tokens with the max_tokens you sent. If they're equal or nearly so, you hit max_tokens.
  3. If completion_tokens is well below max_tokens and prompt_tokens is large, the context window probably filled up. DeepSeek's reference uses length for both cases, so the field alone can't separate them; the comparison in step 2 is how you tell. Anthropic's and Z.ai's documentation name the second case separately, as model_context_window_exceeded. Look at the field in your own responses to see which name you get.

All three descriptions come from the developers' documentation, checked on 20 October 2026: DeepSeek, Anthropic and Z.ai.

What you see finish_reason Cause What to do
Cut off, completion_tokens equals max_tokens length max_tokens reached Raise max_tokens, or ask for the answer in parts
Cut off, completion_tokens far below max_tokens, long input length (or model_context_window_exceeded in some APIs) Context window full Shorten the input or the history, or pick a model with a larger window
Complete but shorter than you wanted stop The model finished, or a stop sequence fired Ask for more detail; check the stop parameter
No text, or a refusal content_filter The response was filtered Rephrase the request
No text, a tool request instead tool_calls The model wants to call a tool Run the tool and send the result back

Fix 1: raise max_tokens#

The most common cause is also the easiest to fix. Set max_tokens yourself, so you know which cap applies. Don't count on the default.

python
from openai import OpenAI

client = OpenAI(base_url="https://api.cheaptokens.dev/v1", api_key="YOUR_API_KEY")

resp = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-V4-Flash-0731",
    messages=[{"role": "user", "content": "Write a detailed guide to setting up a home network."}],
    max_tokens=16000,  # example value: stay at or below the model's output limit
)

choice = resp.choices[0]
print(choice.finish_reason, resp.usage.completion_tokens)

This shows the shape of the call. The key goes in as YOUR_API_KEY here; keep a real one out of code you share.

Raising the number only helps up to the model's own limit. Here are the limits on CheapTokens, checked on 20 October 2026 against the CheapTokens model list:

Model Model ID Max output per answer Context
DeepSeek-V4-Flash (0731) deepseek-ai/DeepSeek-V4-Flash-0731 32,768 tokens 380K
GLM-5.3-Flash zai-org/GLM-5.3-Flash 8,192 tokens 390K
MiniMax-M2.7 MiniMaxAI/MiniMax-M2.7 8,192 tokens 200K

Developers publish their own limits for their own APIs. Z.ai, for example, lists up to 128K output for the GLM-5 series. Those aren't the limits of GLM-5.3-Flash on CheapTokens, which is 8,192 tokens per answer. For anything you build on CheapTokens, use the table above.

Fix 2: when the context window is full#

In a chat, the whole history goes out again with every message, so the input grows each turn. The context window has to hold that history plus the new answer. If the history alone takes nearly all of it, there's almost no room left for a reply.

These windows are large, and one short question won't fill them. Long chats and pasted documents will. What helps:

  • Start a new chat for a new task instead of continuing an old one.
  • Ask the model to summarise the conversation so far, and carry only the summary forward.
  • Cut old messages and attachments you no longer need.
  • If the input itself is huge, pick the model with the biggest window. Among ours that's GLM-5.3-Flash at 390K. Its output limit is 8,192 tokens, so ask for a long result in parts.

Fix 3: get a long answer in parts#

When the answer you want is longer than the model's output limit, no setting will fit it into one reply. Ask for it in pieces: when finish_reason is length, send the partial answer back and ask the model to continue.

python
messages = [{"role": "user", "content": "Write a detailed guide to setting up a home network."}]
parts = []

for _ in range(4):  # example limit: at most 4 rounds
    resp = client.chat.completions.create(
        model="zai-org/GLM-5.3-Flash",
        messages=messages,
        max_tokens=8000,  # example value: below this model's output limit
    )
    choice = resp.choices[0]
    parts.append(choice.message.content)
    if choice.finish_reason != "length":
        break
    messages.append({"role": "assistant", "content": choice.message.content})
    messages.append({"role": "user", "content": "Continue exactly where you stopped. Don't repeat anything."})

text = "".join(parts)

Same caveat: an example of the pattern, not a recorded run. Read the seams between the parts. A model sometimes repeats a sentence or restarts a list at the join.

Each round re-sends everything so far as input, and every output token is billed. A long answer costs more than a short one. Here is an eight-thousand-token answer on 2,000 tokens of input, which fits every model in the table:

Model Cost OpenRouter
GLM-5.3-Flash $0.00036 $0.00069
DeepSeek-V4-Flash $0.00083 $0.0013
MiniMax-M2.7 $0.0013 $0.0102

2,000 input and 8,000 output tokens in total. Prices per 1M tokens are current and change together with our tariffs; the OpenRouter column shows reference prices for the same workload.

When finish_reason is stop#

stop means the model ended the answer. If it ended sooner than you wanted, that isn't a limit problem and a bigger max_tokens changes nothing. Say what you want: the length, the sections, the level of detail. Also check whether the request sets a stop parameter; a stop sequence that shows up in the answer ends it on the spot.

Picking a model by answer length#

Start from the answer you need. If it fits in 8,192 tokens, MiniMax-M2.7 (MiniMaxAI/MiniMax-M2.7) handles it on CheapTokens. Its output is cheaper than the OpenRouter reference price, and it's billed at $0.15 (per 1M output tokens). The price is the same at any hour, there are no peak hours, and the API is OpenAI- and Anthropic-compatible.

Here is the current price list for every model:

Model Context Input $/1M Output $/1M OpenRouter in OpenRouter out
GLM-5.3-Flash reasoning 390K $0.02 $0.04 $0.0413 $0.0758
DeepSeek-V4-Flash 380K $0.015 $0.10 $0.0475 $0.1568
MiniMax-M2.7 180K $0.05 $0.15 $0.30 $1.20

Prices in USD per 1M tokens. OpenRouter figures shown for comparison and may change.

If you haven't sent a request yet, Your first API request with CheapTokens walks through it. For what a token is and why input and output are counted separately, see What is a token in AI?.

Endpoints, model ids and limits for every model are in the CheapTokens docs.