CoreMesh

Claude Extended Thinking Budget: How to Avoid API Errors

Learn how to configure thinking.budget_tokens in Anthropic's Messages API without triggering 400 validation errors against max_tokens.

Claude Extended Thinking Budget: How to Avoid API Errors

Setting a thinking budget in the Anthropic Messages API gives Claude a dedicated token allowance for reasoning before drafting a response. You configure this by passing a thinking parameter with type: "enabled" alongside an integer budget_tokens. Claude runs its internal chain of thought against this target before outputting standard text blocks.

The most common roadblock developers run into is an immediate HTTP 400 validation error. The API enforces strict rules on budget_tokens: it must be at least 1,024 tokens, it cannot equal or exceed max_tokens (except in specific interleaved tool workflows), and it cannot be combined with cache pre-warming. Here is how to configure the budget cleanly across supported models and avoid validation failures.

Setting thinking budget in the Messages API#

To enable manual extended thinking, provide the thinking dictionary with type: "enabled" and a valid integer for budget_tokens. You must set max_tokens high enough to accommodate both the reasoning tokens and your final text response.

Here is a standard Python example using the anthropic SDK on a model that supports manual extended thinking, such as claude-sonnet-4-6:

python
import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=16000,
    thinking={"type": "enabled", "budget_tokens": 10000},
    messages=[
        {
            "role": "user",
            "content": "Are there an infinite number of prime numbers such that n mod 4 == 3?",
        }
    ],
)

for block in response.content:
    match block.type:
        case "thinking":
            print(f"Thinking summary: {block.thinking}")
        case "text":
            print(f"Response: {block.text}")

In raw HTTP calls to the https://api.anthropic.com/v1/messages endpoint, the request body mirrors this structure:

json
{
  "model": "claude-sonnet-4-6",
  "max_tokens": 16000,
  "thinking": {
    "type": "enabled",
    "budget_tokens": 10000
  },
  "messages": [
    {
      "role": "user",
      "content": "Provide a step-by-step mathematical proof."
    }
  ]
}

According to the Anthropic extended thinking documentation, budget_tokens acts as an internal target rather than a strict ceiling. Claude evaluates the problem and can stop thinking well before the budget is exhausted. However, max_tokens remains the hard cap for the total tokens returned during that turn.

Core rules for budget tokens and max tokens#

Every manual extended thinking request must satisfy four core constraints to pass API parameter validation:

  1. Minimum threshold: budget_tokens must be at least 1,024. If you set it to 1,000 or 500, the API returns a 400 error immediately.
  2. Total turn allowance: budget_tokens must be strictly less than max_tokens. Thinking tokens count against the total turn limit defined by max_tokens. If you do not leave headroom for the final output text, your request is rejected.
  3. Cache pre-warming incompatibility: You cannot combine extended thinking with max_tokens: 0. Because budget_tokens must be strictly less than max_tokens, cache pre-warming cannot use manual thinking.
  4. Non-negative values: Token values must be positive integers.

The single exception to the rule that budget_tokens < max_tokens is interleaved thinking during tool use. In an interleaved flow, the budget covers all thinking blocks across a single multi-step assistant turn, allowing the budget to exceed an individual request limit. Outside of that scenario, setting budget_tokens >= max_tokens triggers a validation failure.

To verify your token configuration before sending a payload to the network, you can run this Python validator:

python
def validate_thinking_config(model: str, budget_tokens: int, max_tokens: int, interleaved: bool = False):
    issues = []
    if budget_tokens < 1024:
        issues.append(f"budget_tokens ({budget_tokens}) must be >= 1024")
    if max_tokens <= 0:
        issues.append(f"max_tokens ({max_tokens}) must be greater than 0")
    if not interleaved and budget_tokens >= max_tokens:
        issues.append(f"budget_tokens ({budget_tokens}) must be strictly less than max_tokens ({max_tokens})")

    legacy_manual_models = {"claude-opus-4-5", "claude-sonnet-4-5", "claude-haiku-4-5", "claude-sonnet-4-6", "claude-opus-4-6"}
    if model not in legacy_manual_models:
        issues.append(f"Model '{model}' requires adaptive thinking; type: 'enabled' will return HTTP 400")

    return issues

test_cases = [
    ("claude-sonnet-4-6", 500, 4000, False),
    ("claude-sonnet-4-6", 4000, 4000, False),
    ("claude-sonnet-4-6", 4000, 8000, False),
    ("claude-sonnet-5", 4000, 8000, False),
]

for model, b_tokens, m_tokens, is_interleaved in test_cases:
    errors = validate_thinking_config(model, b_tokens, m_tokens, is_interleaved)
    status = "PASS" if not errors else f"FAIL -> {'; '.join(errors)}"
    print(f"[{model}] budget={b_tokens}, max={m_tokens} : {status}")

Tuning the budget and tracking usage#

Choosing the right budget depends on the complexity of your task, acceptable latency, and cost considerations.

  • Simple reasoning tasks: Start near the minimum of 1,024 tokens. Increase incrementally if you notice Claude skipping deductive steps or making arithmetic errors.
  • Complex problems: For architecture reviews, formal proofs, or intricate logic puzzles, set a starting budget of 16,000 tokens or higher. Keep in mind that higher budgets increase response latency.
  • Requests over 32k tokens: If you need thinking budgets above 32,000 tokens, use the Messages Batches API (POST /v1/messages/batches). Sustained synchronous requests with budgets exceeding 32k tokens frequently hit HTTP client timeouts or intermediate network disconnects.

Thinking tokens are billed as output tokens. To see how many tokens Claude actually spent thinking versus drafting the final answer, inspect the usage object in the API response:

json
{
  "usage": {
    "input_tokens": 25,
    "output_tokens": 4210,
    "output_tokens_details": {
      "thinking_tokens": 3850
    }
  }
}

The field usage.output_tokens_details.thinking_tokens tells you the exact reasoning volume billed. If you stream responses using Server-Sent Events, note that this granular detail is only emitted on the terminal message_delta event.

Developers running agentic workflows from the command line often see unexpected token burn from unconstrained thinking. You can review our operational notes on why Claude Code uses so many tokens and how to check Claude Code usage from the terminal to monitor your billing footprint across different toolchains.

Prompt caching behavior with manual budgets#

If you use prompt caching to reduce input latency and cost on repetitive system prompts or large contexts, pay close attention to how you manage budget_tokens.

When manual extended thinking is active, the value of budget_tokens is compiled directly into the underlying model prompt. Because of this, changing budget_tokens between turns in a multi-turn conversation invalidates prompt cache breakpoints at the message level.

Consider this sequence on claude-sonnet-4-6:

  1. Request 1: Sets budget_tokens: 4000. The API writes the cache (cache_creation_input_tokens: 1370, cache_read_input_tokens: 0).
  2. Request 2: Re-sends the conversation prefix with budget_tokens: 4000. Result: cache hit (cache_read_input_tokens: 1370).
  3. Request 3: Increases budget_tokens: 8000. Result: cache miss (cache_creation_input_tokens: 1370, cache_read_input_tokens: 0).

To maximize cache efficiency in multi-turn dialogues, pick a stable budget for the session and keep it constant across turns.

Interleaved thinking between tool calls#

Interleaved thinking allows Claude to reason between tool executions within a single assistant turn. For example, Claude calls an API, receives a tool result, evaluates the outcome inside an internal thinking block, and decides whether to issue another tool call.

Support for interleaved thinking in manual mode depends heavily on the model version:

  • Claude Opus 4.5 and Claude Sonnet 4.5: Supported in manual mode by including the beta header interleaved-thinking-2025-05-14.
  • Claude Sonnet 4.6: The interleaved-thinking-2025-05-14 header works with manual mode but is deprecated. The recommended path is migrating to adaptive thinking, which interleaves automatically without any headers.
  • Claude Opus 4.6: Manual mode does not support interleaved thinking at all. You must use adaptive thinking if you need mid-turn reasoning with tools on Opus 4.6.
  • Claude Haiku 4.5: Does not support interleaved thinking. The API accepts the header without throwing an error, but ignores it.

As of October 21, 2026, cloud provider endpoints on Amazon Bedrock and Google Cloud also accept the interleaved-thinking-2025-05-14 header without errors, ignoring it on models where manual interleaving is unsupported.

Migrating from manual budgets to adaptive thinking#

Starting with the Claude 4.7 generation and continuing through current models listed on the Anthropic model overview—including claude-sonnet-5, claude-sonnet-5-5, claude-opus-5-5, and claude-fable-5-1—manual extended thinking (type: "enabled") is completely removed. Passing budget_tokens to these models triggers an immediate HTTP 400 error.

On these modern models, you must use adaptive thinking. Instead of setting an exact token number, Claude determines how long to think based on the prompt complexity. You guide reasoning depth using the effort parameter inside output_config.

Here is how the payload changes:

json
// Deprecated manual budget (Claude 4.6 and earlier)
{
  "model": "claude-sonnet-4-6",
  "max_tokens": 16000,
  "thinking": {
    "type": "enabled",
    "budget_tokens": 10000
  }
}

Migrates to:

json
// Modern adaptive thinking (Claude 4.7, Claude 5, and later)
{
  "model": "claude-sonnet-5",
  "max_tokens": 16000,
  "thinking": {
    "type": "adaptive"
  },
  "output_config": {
    "effort": "high"
  }
}

On claude-sonnet-4-6 and claude-sonnet-5-5, effort defaults to high. On models like claude-opus-5-5 and claude-haiku-5-5, it defaults to medium. With adaptive thinking, you do not need the interleaved-thinking-2025-05-14 beta header; tool interleaving happens out of the box.

Common mistakes with thinking budgets#

When managing thinking budgets in production, watch out for these traps:

Setting budget tokens below 1024#

Any integer less than 1,024 causes the API to reject the request payload with a 400 client error. If your workload only needs minimal chain of thought, set budget_tokens: 1024.

Forgetting output headroom in max tokens#

Because thinking tokens count against max_tokens, setting budget_tokens: 4000 alongside max_tokens: 4000 will fail validation. Always add enough headroom to max_tokens for the final text response. For example, if you want a 4,000-token thinking budget and expect an 800-token answer, set max_tokens to at least 5,000.

Sending manual budgets to Claude 4.7 or Claude 5 models#

Newer model releases reject {"type": "enabled", "budget_tokens": ...} with HTTP 400. If you are upgrading your model IDs to claude-sonnet-5 or claude-opus-5-5, switch to {"type": "adaptive"} and remove the budget_tokens property entirely.

Adjusting budgets across turns in cached conversations#

Because the thinking budget is formatted into the prompt template, updating budget_tokens mid-conversation invalidates prompt cache read hits. Lock in a single budget size for the entire session.

Synchronous requests with budgets above 32k#

Setting thinking budgets higher than 32,000 tokens often results in Claude thinking for several minutes before writing output tokens. Standard HTTP client libraries and API gateways will hit gateway timeouts. Route these through the Message Batches API (POST /v1/messages/batches) instead.

Quick reference checklist#

Before deploying your extended thinking calls, verify each requirement:

  • Parameter type: Set thinking.type to "enabled" for manual budgets on supported models (such as claude-sonnet-4-6 or claude-opus-4-5).
  • Floor: Confirm budget_tokens >= 1024.
  • Ceiling: Confirm max_tokens > budget_tokens by an amount large enough to hold the generated response.
  • Batching: Route any request with budget_tokens > 32000 through the Message Batches API.
  • Caching: Keep budget_tokens identical across turns to preserve cache breakpoints.
  • Modern models: If calling claude-sonnet-5, claude-opus-5-5, or claude-fable-5-1, switch to thinking: {"type": "adaptive"} and steer depth with output_config.effort.

Quick answers

What is the minimum budget_tokens value in the Anthropic API?

The minimum allowed value for budget_tokens is 1,024 tokens. Supplying any value lower than 1,024 results in an immediate HTTP 400 validation error.

Can budget_tokens be equal to or greater than max_tokens?

In standard requests, no. The thinking budget must be strictly less than max_tokens because thinking tokens count against the total turn limit. The only exception is interleaved thinking during tool use, where the budget spans multiple thinking blocks across one assistant turn.

Why does Claude return an error when I set budget_tokens on Claude Sonnet 5?

Starting with Claude 4.7 and Claude 5 models, manual extended thinking budgets are removed. Sending thinking: {type: 'enabled', budget_tokens: N} returns an HTTP 400 error; you must use thinking: {type: 'adaptive'} instead.

How can I check how many tokens Claude actually spent thinking?

Inspect the usage.output_tokens_details.thinking_tokens field in the API response. For streaming calls, this breakdown appears in the final message_delta event.

Did this solve it?

One tap. No account.

Saved you an hour? Send a tip.

USDC or ETH on Base, Ethereum, Arbitrum and more. Keeps the notes free and the examples running.

Base

Network

0xc783bc5c3fa14cEC3f09A22284bC91C5AF0d59e1
Open in wallet · 5 USDC

On a computer? Scan the code with your phone wallet, or copy the address.

Pick the network your wallet or exchange uses. USDC works on all six; ETH on Base, Ethereum, Arbitrum and Optimism. Don't send on Tron or Solana: this address doesn't exist there. Tips are optional and unlock nothing; every guide stays free.

Discussion

Start the discussion

Indra Wijaya

Builds and runs AI agents, bots and content pipelines, and writes down what works and what broke.

About · Email · RSS

Keep reading

New notes, no spam.

One post at a time, only when there's something worth reading. Follow in any feed reader.

Subscribe via RSS