Claude's Extended Thinking is one of its most powerful capabilities—when it works. Watching Claude reason through a complex problem step by step, surface hidden assumptions, and arrive at a well-grounded answer is genuinely impressive. But many developers and power users hit a wall early: the thinking stops partway through, a timeout error is returned, or the API bill arrives with numbers that weren't expected.
As an indie developer, I run Extended Thinking in a couple of small apps I maintain on my own—drafting support replies and classifying incoming questions. In the early days, a nightly batch would fail on timeouts about half the time, and opening the morning logs became a small dread. None of the causes were dramatic; every one of them was a minor configuration mistake. What follows is what I checked, hands on keyboard, so that fewer people get stuck in the same places.
This guide takes a systematic look at the most common Extended Thinking failures, explains what's actually happening under the hood, and gives you practical solutions—including working code—to fix each one.
How Extended Thinking Works (and Why It Fails)
Before fixing problems, it helps to understand the mechanism.
When you enable Extended Thinking, Claude generates a thinking block before composing its final answer. Inside this block, Claude explores hypotheses, tests its own reasoning, considers counterarguments, and works toward a conclusion. This thinking content is generated as tokens—which is why the budget_tokens parameter exists. It sets the maximum number of tokens Claude is allowed to spend on thinking before it must produce a final answer.
There are a few key constraints to keep in mind:
Extended Thinking is available on Claude Sonnet 4.6 and Claude Opus 4.6 as of April 2026. Haiku models do not support it. Enabling Extended Thinking significantly increases cost compared to standard generation. The budget_tokens value represents a ceiling, not a guarantee—Claude may use less, but can use up to the limit. And critically, max_tokens must cover both the thinking budget and the final answer.
Troubleshooting by Failure Pattern
Pattern 1: Timeout errors returned from the API
This is the most common Extended Thinking issue. You send a request and receive a timeout or APITimeoutError back.
What's happening
Without streaming, your HTTP connection must stay open until the first token is returned. For Extended Thinking requests with a large budget_tokens value, Claude may take a significant amount of time before generating any output—long enough to exceed the default request timeout.
Fix: Use streaming
Streaming keeps the connection alive as tokens are generated, effectively solving timeout issues for the vast majority of cases.
import anthropic
client = anthropic.Anthropic()
# Streaming approach—timeout-resistant
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=20000,
thinking={
"type": "enabled",
"budget_tokens": 10000
},
messages=[
{"role": "user", "content": "Your complex question here"}
]
) as stream:
# Stream events as they arrive
for event in stream:
pass # Handle events as needed
# Get the complete final message
final = stream.get_final_message()
# Extract thinking and answer
for block in final.content:
if block.type == "thinking":
print(f"Thinking: {block.thinking[:200]}...")
elif block.type == "text":
print(f"Answer: {block.text}")Fix: Start with smaller budget_tokens values
If you set budget_tokens to 100,000 for a question that only needs 8,000 tokens of thinking, you're creating unnecessary risk and cost. Start conservative and tune upward.
# Preset budgets by problem complexity
BUDGET_PRESETS = {
"simple": 5_000, # Basic math, straightforward logic
"moderate": 10_000, # Multi-step reasoning, analysis
"complex": 20_000, # Strategic design, complex analysis
"extreme": 50_000, # Research-level, philosophical problems
}Pattern 2: Thinking block is present but the final answer is empty or truncated
Claude completes the thinking phase but returns little or nothing in the actual response text.
What's happening
max_tokens is not set high enough. In Extended Thinking mode, max_tokens covers both the thinking tokens and the final answer tokens. If budget_tokens is close to or equal to max_tokens, there may not be enough token headroom left for a proper answer.
Fix: Give max_tokens enough runway
# Problematic configuration
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=10000, # 10k total
thinking={
"type": "enabled",
"budget_tokens": 10000 # Thinking can consume ALL of max_tokens!
},
...
)
# Correct configuration
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=22000, # 15k thinking + 7k for answer
thinking={
"type": "enabled",
"budget_tokens": 15000
},
...
)Rule of thumb: Set max_tokens to at least budget_tokens + 5000. For detailed technical answers, allow budget_tokens + 10000 to be safe.
Pattern 3: Thinking loops or repeats the same analysis
When you read the thinking block, Claude appears to be going in circles—re-examining the same considerations multiple times without making progress toward an answer.
What's happening Ambiguous or contradictory constraints in your prompt can cause Claude to keep reconsidering its approach without being able to commit to one. This wastes thinking tokens and often produces a weaker final answer.
Fix: Provide structure and clear constraints
# Ambiguous prompt—likely to cause thinking loops
messages = [
{"role": "user", "content": "Evaluate this business plan."}
]
# Structured prompt—gives Claude a clear path forward
messages = [
{
"role": "user",
"content": """
Evaluate the following business plan across three dimensions:
1. Market size — assess the claimed TAM with reference to verifiable data
2. Competitive differentiation — compare against the three named competitors
3. Financial feasibility — review the three-year cash flow projections
Constraints:
- Keep each dimension to 150-250 words
- Avoid vague language like "may" or "could"—ground claims in evidence
- End with an overall rating from 1 to 5 with a one-sentence rationale
Business plan:
{business_plan}
"""
}
]Pattern 4: Costs are much higher than expected
Extended Thinking is priced on output tokens, including thinking tokens. Unexpected costs usually mean thinking is consuming more tokens than anticipated.
Monitor your token usage
response = client.messages.create(...)
# Count thinking tokens separately
thinking_tokens = 0
answer_tokens = 0
for block in response.content:
if block.type == "thinking":
# Approximate token count from character length
thinking_tokens += len(block.thinking) // 4
elif block.type == "text":
answer_tokens += len(block.text) // 4
total_output = response.usage.output_tokens
print(f"Thinking tokens (approx): {thinking_tokens:,}")
print(f"Answer tokens (approx): {answer_tokens:,}")
print(f"Total output tokens: {total_output:,}")
# Rough cost estimate for Sonnet 4.6
cost = (response.usage.input_tokens * 3 + total_output * 15) / 1_000_000
print(f"Estimated cost: ${cost:.4f}")Cost optimization: Only activate Extended Thinking when you need it
def ask_claude(question: str, complexity: str = "auto") -> str:
use_thinking = complexity == "high" or (
complexity == "auto" and _needs_deep_reasoning(question)
)
kwargs = {
"model": "claude-sonnet-4-6",
"max_tokens": 8000,
"messages": [{"role": "user", "content": question}]
}
if use_thinking:
kwargs["thinking"] = {"type": "enabled", "budget_tokens": 10000}
kwargs["max_tokens"] = 20000
response = client.messages.create(**kwargs)
return next(b.text for b in response.content if b.type == "text")
def _needs_deep_reasoning(question: str) -> bool:
reasoning_signals = [
"prove", "optimize", "compare", "design", "why does", "analyze",
"trade-off", "best approach", "evaluate"
]
return any(signal in question.lower() for signal in reasoning_signals)