handling-stop-reasons changedbuild-with-claude/handling-stop-reasons
Nearest release: v2.1.312, published under an hour before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Recorded here
Lines+17added
Lines−17removed
From line
4
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits23to this page, all time
The whole hunk
from line 4, old and new numbered
/
from line 4
44description: Learn what each stop_reason value means and how to handle truncation, tool use, paused turns, and refusals in your application.
55---
66
7Every Messages API response includes a `stop_reason` field that tells you why Claude stopped generating. Check this field to decide whether to use the response as-is, continue the conversation, retry, or fall back to another model.
7Every Messages API response includes a [`stop_reason`](https://platform.claude.com/docs/en/api/messages/create#message.stop_reason) field that tells you why Claude stopped generating. Check this field to decide whether to use the response as-is, continue the conversation, retry, or fall back to another model.
88
99For the full response schema, see the [Messages API reference](https://platform.claude.com/docs/en/api/messages/create).
1010
from line 18
1818| [`tool_use`](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#tool-use) | Claude is calling a tool. | Run the tool and return the result. A server tool call still missing its result block completes in a later response. |
1919| [`pause_turn`](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn) | A server-tool loop reached its iteration limit. | Send the assistant content back to continue. |
2020| [`refusal`](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#refusal) | Claude declined to respond. | Read `stop_details` and [retry on a fallback model](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback). |
21| [`model_context_window_exceeded`](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#model-context-window-exceeded) | The response filled the model's context window. | Treat the response as truncated. |
21| [`model_context_window_exceeded`](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#model-context-window-exceeded) | The response filled the model’s context window. | Treat the response as truncated. |
2222
2323## The stop\_reason field
2424
from line 211
211211 **Common causes:**
212212
213213 * Adding text blocks immediately after tool results (the history then shows user text after every tool result, so Claude ends its turn to follow that pattern)
214 * Sending Claude's completed response back without adding anything (Claude already determined it's done, so it will remain done)
214 * Sending Claude’s completed response back without adding anything (Claude already determined it’s done, so it will remain done)
215215
216216 **How to prevent empty responses:**
217217
from line 728
728728 **Best practices:**
729729
730730 1. **Never add text blocks immediately after tool results:** This sets a pattern of user input after every tool use, and Claude follows that pattern by ending its turn.
731 2. **Don't retry empty responses without modification:** Sending the empty response back won't help.
732 3. **Use continuation prompts as a last resort:** Only if these fixes don't resolve the issue.
731 2. **Don’t retry empty responses without modification:** Sending the empty response back won’t help.
732 3. **Use continuation prompts as a last resort:** Only if these fixes don’t resolve the issue.
733733</Accordion>
734734
735735### max\_tokens
736736
737Claude stopped because it reached the `max_tokens` limit specified in your request.
737Claude stopped because it reached the [`max_tokens`](https://platform.claude.com/docs/en/api/messages/create#create.max_tokens) limit specified in your request.
738738
739739<CodeGroup>
740740 ```bash cURL
from line 884
884884</CodeGroup>
885885
886886<Accordion title="Incomplete tool use blocks">
887 If Claude's response is cut off because it hit the `max_tokens` limit, and the truncated response contains an incomplete tool use block, you'll need to retry the request with a higher `max_tokens` value to get the full tool use.
887 If Claude’s response is cut off because it hit the `max_tokens` limit, and the truncated response contains an incomplete tool use block, you’ll need to retry the request with a higher `max_tokens` value to get the full tool use.
888888
889889 <CodeGroup exclude="shell:cURL, shell:CLI">
890890 <CodeGroupItem language="cURL">
from line 1046
10461046
10471047### stop\_sequence
10481048
1049Claude encountered one of your custom stop sequences.
1049Claude encountered one of your custom [stop sequences](https://platform.claude.com/docs/en/api/messages/create#create.stop_sequences).
10501050
10511051<CodeGroup>
10521052 ```bash cURL
from line 1478
14781478 ```
14791479</CodeGroup>
14801480
1481A `tool_use` response can also contain a `server_tool_use` block whose `id` has no matching result block. That server tool call is not complete, and this response does not carry its result. In the common case, Claude calls a [server tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools) and one of your client tools in the same group of parallel tool calls: the API returns without running the server tool so that you can run the client tools first. There is no other marker for the state; detect it by checking each `server_tool_use` or `mcp_tool_use` block's `id` for a matching result block.
1481A `tool_use` response can also contain a `server_tool_use` block whose `id` has no matching result block. That server tool call is not complete, and this response does not carry its result. In the common case, Claude calls a [server tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools) and one of your client tools in the same group of parallel tool calls: the API returns without running the server tool so that you can run the client tools first. There is no other marker for the state; detect it by checking each `server_tool_use` or `mcp_tool_use` block’s `id` for a matching result block.
14821482
14831483<Note>
1484 With [programmatic tool calling](https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling), the same response shape means something different. The client `tool_use` block comes from code that is running in the `code_execution` tool rather than from Claude directly, and its `caller` field names the `code_execution` block that called it. That code has already started: it is paused waiting for your `tool_result` blocks, and sending them resumes the execution instead of starting a deferred tool. The `code_execution` block's own result block arrives once the code completes, which can take more than one round of tool results. The follow-up user message itself is the same in both cases; with programmatic tool calling, also pass back the `id` from the response's `container` field, as that page shows.
1484 With [programmatic tool calling](https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling), the same response shape means something different. The client `tool_use` block comes from code that is running in the `code_execution` tool rather than from Claude directly, and its `caller` field names the `code_execution` block that called it. That code has already started: it is paused waiting for your `tool_result` blocks, and sending them resumes the execution instead of starting a deferred tool. The `code_execution` block’s own result block arrives once the code completes, which can take more than one round of tool results. The follow-up user message itself is the same in both cases; with programmatic tool calling, also pass back the `id` from the response’s `container` field, as that page shows.
14851485</Note>
14861486
14871487```json A mixed tool_use response
from line 1504
15041504}
15051505```
15061506
1507The continuation is a user message of `tool_result` blocks, one for every `tool_use` block in the response (see [Handle tool calls](https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls)), with two extra rules: that message must contain nothing except the `tool_result` blocks, and the request must keep the same `tools` array. A resume request that no longer defines the waiting server tool fails with a 400 whose message ends ``but no `web_search` tool was provided``. The API attaches your results to the still-open assistant turn, runs the deferred server tool (for paused code execution, resumes it), and continues the turn. For a server tool Claude called directly, the next response's `content` starts with the result block that answers the previous response's `server_tool_use` `id`.
1507The continuation is a user message of `tool_result` blocks, one for every `tool_use` block in the response (see [Handle tool calls](https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls)), with two extra rules: that message must contain nothing except the `tool_result` blocks, and the request must keep the same `tools` array. A resume request that no longer defines the waiting server tool fails with a 400 whose message ends ``but no `web_search` tool was provided``. The API attaches your results to the still-open assistant turn, runs the deferred server tool (for paused code execution, resumes it), and continues the turn. For a server tool Claude called directly, the next response’s `content` starts with the result block that answers the previous response’s `server_tool_use` `id`.
15081508
15091509```json The follow-up user message
15101510{
from line 1746
17461746</CodeGroup>
17471747
17481748<Note>
1749 Your application should handle `pause_turn` in any agent loop that uses server tools. Add the assistant's response to your messages array and make another API request to let Claude continue.
1749 Your application should handle `pause_turn` in any agent loop that uses server tools. Add the assistant’s response to your messages array and make another API request to let Claude continue.
17501750</Note>
17511751
17521752### refusal
from line 1894
18941894</CodeGroup>
18951895
18961896<Tip>
1897 If you encounter `refusal` stop reasons frequently while using Claude Sonnet 4.5 ([deprecated](https://platform.claude.com/docs/en/about-claude/model-deprecations)) or Claude Opus 4.1 (the latter [retired, except on Bedrock and Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/about-claude/model-deprecations)), you can try updating your API calls to use Haiku 4.5 (`claude-haiku-4-5-20251001`), which has different usage restrictions. Learn more about [understanding Sonnet 4.5's API safety filters](https://support.claude.com/en/articles/12449294-understanding-sonnet-4-5-s-api-safety-filters).
1897 If you encounter `refusal` stop reasons frequently while using Claude Sonnet 4.5 ([deprecated](https://platform.claude.com/docs/en/about-claude/model-deprecations)) or Claude Opus 4.1 (the latter [retired, except on Bedrock and Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/about-claude/model-deprecations)), you can try updating your API calls to use Haiku 4.5 (`claude-haiku-4-5-20251001`), which has different usage restrictions. Learn more about [understanding Sonnet 4.5’s API safety filters](https://support.claude.com/en/articles/12449294-understanding-sonnet-4-5-s-api-safety-filters).
18981898</Tip>
18991899
1900On a refusal, the `stop_details` object identifies the policy category that triggered it. The categories and the full refusal response shape are covered in [What a refusal looks like](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#refusal-response). `stop_details` is `null` for all stop reasons other than `refusal`.
1900On a refusal, the [`stop_details`](https://platform.claude.com/docs/en/api/messages/create#message.stop_details) object identifies the policy category that triggered it. The categories and the full refusal response shape are covered in [What a refusal looks like](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#refusal-response). `stop_details` is `null` for all stop reasons other than `refusal`.
19011901
19021902A refused request on Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5, or Claude Haiku 5.5 can usually be served by retrying on another Claude model. [Refusals and fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback) shows how to set up that retry, server-side or in your client. Claude Haiku 5.5 has no server-side fallback, so set up its retry [in your client](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#client-side-fallback). If you build the retry yourself from Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, or Claude Sonnet 5.5, [fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) covers how to avoid paying the prompt-cache cost twice.
19031903
19041904### model\_context\_window\_exceeded
19051905
1906Claude stopped because it reached the model's context window limit. This lets you request the maximum possible tokens without knowing the exact input size.
1906Claude stopped because it reached the model’s context window limit. This lets you request the maximum possible tokens without knowing the exact input size.
19071907
19081908<Note>
1909 This stop reason is currently typed only in the SDK's `beta` (csharp, go: `Beta`; java: `beta()`) namespace, so the following examples call `client.beta.messages` (csharp, go: `client.Beta.Messages`; java: `client.beta().messages()`; php: `$client->beta->messages`) and use the `Beta`-prefixed types. On Sonnet 4.5 (deprecated) and newer models, the API returns this value without a beta header. For earlier models, add the `model-context-window-exceeded-2025-08-26` beta header to enable it.
1909 This stop reason is currently typed only in the SDK’s `beta` (csharp, go: `Beta`; java: `beta()`) namespace, so the following examples call `client.beta.messages` (csharp, go: `client.Beta.Messages`; java: `client.beta().messages()`; php: `$client->beta->messages`) and use the `Beta`-prefixed types. On Sonnet 4.5 (deprecated) and newer models, the API returns this value without a beta header. For earlier models, add the `model-context-window-exceeded-2025-08-26` beta header to enable it.
19101910</Note>
19111911
19121912<CodeGroup>
from line 2582
25822582
25832583## Stop reasons versus errors
25842584
2585It's important to distinguish between `stop_reason` values and actual errors:
2585It’s important to distinguish between `stop_reason` values and actual errors:
25862586
25872587### Stop reasons (successful responses)
25882588
No line in this hunk matches that.