AI News

Claude Opus 5.5 Breaking Changes: 6 Errors, 2 Silent

Abhishek Bahukhandi

Abhishek Bahukhandi

•8 min read
Taqari cover art for a breakdown of the Claude Opus 5.5 breaking changes and the two that fail silently
Taqari cover art for a breakdown of the Claude Opus 5.5 breaking changes and the two that fail silently
Claude Opus 5.5 breaking changes go past the usual four: six request settings now return 400, and two more change how your app behaves without any error.

Most write-ups of the Claude Opus 5.5 breaking changes count four. Read the request requirements in Anthropic's own migration guide and the count is higher: six settings that now return a 400, plus two more that change how your application behaves while every request still returns 200.

The second group is the one that reaches your users. A 400 shows up in your error rate minutes after you deploy. A response that quietly changed shape does not. This post is about both, in the order you should fix them.

What actually shipped on 22 September

Anthropic released Claude Opus 5.5 on 22 September 2026 as claude-opus-5-5 — a fixed model ID with no date suffix. The 1M token context window is the default with no beta header, and maximum output is 128,000 tokens. Adaptive thinking is always on, and the effort parameter is the only request parameter that controls how much the model reasons.

It is available on the Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud and Microsoft Foundry. We covered what Opus 5.5 actually costs to run separately; this post is only about the request and response contract. One useful note before you start: if you use Claude Managed Agents rather than the Messages API directly, no change beyond the model name is required.

The six Claude Opus 5.5 breaking changes that return 400

Each of these is an invalid_request_error. That is the good news — your test suite finds them for you.

1. Thinking cannot be disabled

On Claude Opus 5, thinking: {"type": "disabled"} was accepted at effort high or below. On Opus 5.5 it is rejected, and so is a manual budget via thinking: {"type": "enabled", "budget_tokens": N}. The error is explicit about the replacement:

"thinking.type.disabled" is not supported for this model.
Use "thinking.type.adaptive" and "output_config.effort"
to control thinking behavior.

Omit the thinking field, or send thinking: {"type": "adaptive"}, which is equivalent. No beta header is involved. If you disabled thinking for latency or cost, lower effort instead.

Two consequences follow for any workload that previously ran without thinking. max_tokens stays a hard limit on total output — thinking plus response text — so revisit it. And thinking tokens are billed as output tokens even when the thinking text is not returned to you, so the same request can produce more billable output than it used to.

2. Forced tool use is rejected

tool_choice set to {"type": "any"} or {"type": "tool", "name": "..."} returns a 400, and the same validation applies to the token counting endpoint. Only auto (the default) and none are supported.

If you were forcing a tool to guarantee schema-valid JSON, keep tool_choice: {"type": "auto"} and set strict: true with strict tool use, or move the schema to structured outputs. If you were forcing a call so the model would act rather than reply in prose, say in the prompt when the tool applies.

3. Sampling parameters and prefill

These two are absent from most of the migration listicles, and they break older code more often than the tool-choice change does.

temperature, top_p and top_k

Omit them, or leave them at their defaults. Any other value is rejected. Steer the model with prompting instead. Code that sets temperature: 0 for determinism — a very common pattern in extraction and classification pipelines — now fails outright.

Assistant prefill

Do not end messages with a prefilled assistant turn. It is rejected. Use structured outputs, or put the constraint in the system prompt.

4. The older computer use tool, on two platforms

On the Claude API and Google Cloud, Opus 5.5 accepts computer use only as the computer_toolset_20260801 toolset; a request declaring the earlier computer_20251124 tool returns a 400. Drop the computer-use-2025-11-24 beta header, replace the tools entry, and update your agent loop for member tool_use blocks, batch actions and toolset_name on results.

On Amazon Bedrock the earlier tool still works, so no change is needed there. The browser use tool is unaffected.

5. Edited thinking blocks in a tool-use loop

When you return tool results, pass the thinking blocks from each assistant response back complete and unmodified — including the ones whose thinking field is empty. Echo the assistant message as you received it rather than filtering its content blocks by type or rebuilding it. Edited, reordered or partially dropped thinking blocks are rejected with a 400.

This one catches a lot of hand-rolled harnesses, because filtering an assistant turn down to "just the useful blocks" was a harmless tidy-up on older models.

6. Replaying a thinking block after the prefix changed

The API checks whether anything before an Opus 5.5 thinking block — the system prompt, the tools array, or an earlier message — has changed since that block was produced. For accounts created on or after 31 August 2026, that check is enforced by default, and a request that replays a block after such a change returns a 400.

You can opt into dropping the affected blocks instead, with the thinking-binding-controls-2026-08-01 beta header and prefix_mismatch_behavior set to "drop_block". The better fix is structural: keep the conversation append-only, and change instructions or tools with mid-conversation system messages rather than by editing history.

The two changes that return 200

Now the ones nothing tells you about.

Your progress updates go quiet between tool calls

On Opus 5, the short notes a model writes between tool calls came back as text blocks. On Opus 5.5 that narration comes back as progress-update thinking blocks — at most one before each tool call — and at the default thinking.display of "omitted" their text is empty.

No request fails. Your agent still works. It just stops telling anyone what it is doing. To get the updates back, set a display value that returns their text — "updates" (beta, via the thinking-display-updates-2026-08-18 header) returns the progress notes while reasoning stays hidden, and "summarized" returns both — then render each non-empty thinking block ahead of the tool_use block it precedes, and pass the blocks back unchanged.

A related client-side trap: because every response can now begin with one or more thinking blocks, code that reads content[0].text breaks, and so does a stream handler that assumes the first content_block_start event is text. Select content blocks by their type field, never by position.

The default effort level dropped from high to medium

Claude Opus 5 defaulted to high. Opus 5.5 defaults to medium. A request that omits effort therefore runs a level lower than it did before, with no indication that anything changed.

What makes this genuinely awkward is that the error cuts both ways: at the same effort level, Opus 5.5 tends to think more per turn than Opus 5, most noticeably at xhigh and max. So carrying a setting across is wrong whether you pinned a level or relied on the default. Set effort explicitly, re-run your sweep on your own evals, and leave room in max_tokens for the extra thinking.

The takeaway

The breaking changes that return 400 are the cheap ones — your test suite finds them before your users do. Budget your migration time for the two that return 200: progress narration moving into thinking blocks and disappearing at the default display setting, and a request that omits effort silently dropping from high to medium. Neither one appears in an error rate.

Why the silent failure is the expensive one

Anything interesting we build at Taqari streams something to a browser while work is still in progress. When we wrote about streaming test results to the browser with SSE, the lesson we kept relearning was that the transport is easy and the contract is hard: the failure mode that hurts is not a dropped connection, it is a stream that stays open and stops saying anything useful.

A model provider changing which block type carries your progress text is exactly that failure, arriving from outside your codebase. Nobody gets paged for silence — no stack trace, no 5xx, just a spinner that runs longer than users will wait and a support ticket three days later saying the tool "feels stuck".

The defensive move is cheap: assert on the shape of the response in a test, not just the status code. One test that fails when your progress updates stop arriving beats a dashboard that only watches error rates.

A migration order that works

  1. Swap the model ID and run your existing tests. Every 400 in the list above surfaces itself. Let the suite do the inventory.
  2. Clear the rejections in roughly this order: thinking, tool_choice, sampling parameters, prefill, computer use.
  3. Make the conversation harness append-only and echo assistant turns verbatim. This covers items 5 and 6 together.
  4. Set effort explicitly and re-run your sweep. Raise max_tokens; start around 64k if you run at xhigh or max.
  5. Set thinking.display if your interface shows anything between tool calls.
  6. Handle stop_reason: "refusal". Opus 5.5 runs more safeguard classifiers than Opus 5, so expect stop_details.category values such as "bio" and "reasoning_extraction" alongside "cyber" — and note that a refusal returns HTTP 200, not an error.
  7. Re-baseline cost and latency at the level you settled on, in a development environment, before you move production traffic.

If you use Claude Code, the bundled Claude API skill will do the mechanical part: /claude-api migrate this project to claude-opus-5-5 applies the ID swap and the breaking parameter changes across a code base you scope, then hands you a checklist of what still needs a human. Treat the checklist as the real work.

What this means if you are preparing for interviews

Migrations like this are a growing share of what working engineers do, and they are hard to bluff. Reading a changelog carefully, separating a loud failure from a silent one, and staging a rollout are judgement, not recall — which is why interviewers reach for them.

The question to be ready for is not "what does the effort parameter do". It is "a provider changed a response shape, nothing errored, and quality dropped — how would you have caught it?" A good answer talks about asserting on structure, baselining behaviour before a switch, and rolling out to a slice of traffic first. If you want to practise answering that sort of question out loud rather than in your head, that is what Taqari's free AI mock interviews are for.

The short version

Change the model ID, then clear the six rejections in the order above. Spend the time you save on the two changes that return 200, the ones your monitoring will not catch: your progress narration has moved into thinking blocks, and your default effort level has quietly dropped a notch. Full detail is in Anthropic's what's new page for Opus 5.5 and the API release notes.

Frequently asked questions

What are the Claude Opus 5.5 breaking changes?

+

Six request settings now return a 400: disabled thinking, manual thinking budgets, forced tool use, non-default sampling parameters, assistant prefill, and the older computer use tool on two platforms. Two more change behaviour without an error: progress text moves into thinking blocks, and the default effort level drops to medium.

Why does Claude Opus 5.5 return a 400 when I disable thinking?

+

Adaptive thinking is always on, so thinking type disabled and manual budget_tokens values are both rejected with an invalid_request_error. Omit the thinking field entirely, or send thinking type adaptive, which is equivalent. Use the effort parameter where you previously turned thinking off to save latency or tokens.

How do I force a tool call on Claude Opus 5.5?

+

You cannot. tool_choice types any and tool both return a 400, and the same validation applies to the token counting endpoint. Keep tool_choice auto and set strict true with strict tool use, move the schema to structured outputs, or state in the prompt when the tool applies.

Did the default effort level change in Claude Opus 5.5?

+

Yes. Claude Opus 5 defaulted to high effort and Claude Opus 5.5 defaults to medium, so a request that omits effort runs one level lower than before. Opus 5.5 also thinks more per turn at the same level, so re-run an effort sweep instead of carrying settings over.

Why did my streaming UI go quiet after upgrading to Claude Opus 5.5?

+

The short notes the model writes between tool calls now arrive as progress-update thinking blocks instead of text blocks, and their text is empty at the default display setting of omitted. No request fails. Set display to updates or summarized and render the non-empty thinking blocks.

Does a model migration like this come up in technical interviews?

+

Increasingly, yes. Reading a provider changelog, telling a loud failure from a silent one, and planning a staged rollout are the parts of the job that are hard to fake. Expect questions about how you would verify a behaviour change that raises no error at all.

Sources

Did you find this helpful?

Share this guide with your circle.

#claude opus 5.5 breaking changes#claude opus 5.5 migration#claude opus 5.5 api#claude effort parameter#thinking cannot be disabled#tool_choice any not supported