Blog

Claude "temperature is deprecated for this model": what changed on 21 October and how to fix it

Ramashankar S · · Updated · 9 min read

If you upgraded the Anthropic SDK recently and your Claude calls started failing, the error probably looks like this:

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "`temperature` is deprecated for this model."
  },
  "request_id": "req_..."
}

The short fix: stop sending temperature, top_p and top_k to Claude. The rest of this post explains why it happened, why Python users often see a different error, which frameworks still send these values for you, and what to do if your app depended on a low temperature.

What changed on 21 October

Anthropic released a new API version, 2026-10-21. Under it, a request that includes temperature, top_p or top_k returns a 400 error, "even at the parameter's default value." That last part is what catches people. Sending temperature: 1, which used to be harmless, now fails too.

This didn't come out of nowhere. Since Claude Opus 4.7 in April, the newer models have refused any non-default sampling value. The new API version stops accepting the parameters altogether.

You get the new version in one of two ways:

  • You upgraded the SDK. The first releases that use 2026-10-21 are anthropic 2.0.0 for Python and @anthropic-ai/sdk 1.0.0 for TypeScript, along with new major versions of the C#, Go, Java, PHP and Ruby SDKs and the CLI. Anthropic's SDKs send whichever API version was current when their major version came out, so a major upgrade moves you onto the new rules without any other change in your code.
  • You call the HTTP API yourself and set the anthropic-version header to 2026-10-21.

If you're still on an older SDK major version, or you send anthropic-version: 2023-06-01, the new rule doesn't apply to you yet.

Two different errors, depending on your SDK

Python users often never see the 400. Recent versions of the anthropic package removed temperature, top_p and top_k from messages.create() entirely, so passing one fails inside the SDK before any request is sent:

TypeError: Messages.create() got an unexpected keyword argument 'temperature'

The SDK's migration notes suggest passing the values through extra_body for older models that still use them. That workaround is exactly what turns into the 400 once you're on version 2.0 and API version 2026-10-21. So if you see the TypeError, delete the argument rather than moving it into extra_body.

Which error you have, what causes it and the fix

Which requests fail

Which Claude requests return a 400 under each API version
API version 2023-06-01API version 2026-10-21
Claude 4.7 and later (for example Opus 5.5, Sonnet 5.5, Fable 5.1), and Claude Mythos Preview400 if you send a non-default value400 if you send the parameter at all
Earlier models (for example Sonnet 4.6, Haiku 4.5)Any value works400 if you send the parameter at all

On Amazon Bedrock, version 2026-10-21 is only available for Claude 4.7 and later. More on Bedrock below.

The fix

Remove the three parameters. With the Python SDK:

import anthropic

client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=1024,
    # temperature=0.2,  # remove it: a TypeError on recent SDKs, a 400 on API version 2026-10-21
    messages=[{"role": "user", "content": "Classify this support ticket: ..."}],
)
print("".join(b.text for b in message.content if b.type == "text"))

If one shared function builds requests for several providers, strip the parameters for Claude only, so your GPT and Gemini calls keep their settings:

SAMPLING_KEYS = ("temperature", "top_p", "top_k")

def request_params(model: str, params: dict) -> dict:
    if model.startswith("claude"):
        return {k: v for k, v in params.items() if k not in SAMPLING_KEYS}
    return params

Calling Claude through an OpenAI-compatible endpoint doesn't get you around this. Anthropic's own OpenAI SDK compatibility layer already returns a 400 on Claude 4.7 and later for any temperature below 1, any top_p other than the default, or both set together. Many gateways pass these values straight through to the model, so the reliable fix is the same on every route: don't send them to Claude.

When a framework sends it for you

Often the parameter isn't in your code at all. It's in a framework default or a config file. Where the main ones stood on 31 October:

  • LangChain. langchain-anthropic 1.7.7 dropped its cap on the Anthropic SDK version, so upgrading it can pull in SDK 2.x. ChatAnthropic only sends temperature if you set it, but when you do, it passes it through extra_body, which gets you the 400 on SDK 2.x. Remove temperature from your ChatAnthropic(...) setup.
  • Vercel AI SDK. @ai-sdk/anthropic still sends anthropic-version: 2023-06-01 and drops sampling settings for models that reject them, with an "unsupported" warning. The Bedrock provider got the same fix after a bug report in September.
  • LlamaIndex. llama-index-llms-anthropic 0.12.3 has an open bug: it breaks on SDK 1.x because of the temperature argument, and on 2.x for a different reason. The reporter's workaround is pinning anthropic<1 until a fix ships.
  • Pydantic AI. It drops the parameters and logs a warning on every request.

If you use another framework, search its config for temperature, top_p and top_k, and check whether it pins the Anthropic SDK version.

Staying on the old API version for now

If you can't change the request code yet, you can stay on the old behavior two ways:

  • Pin the SDK below the new major version: anthropic<2 for Python, @anthropic-ai/sdk<1 for TypeScript. Anthropic's own docs suggest pinning the version you use today in some migration cases. This is the safer option.
  • Override the header: anthropic.Anthropic(default_headers={"anthropic-version": "2023-06-01"}). Anthropic documents this, but warns that overriding default headers "might result in incorrect types and other unexpected or undefined behavior in the SDK."

Either way, it only helps on older models. Claude 4.7 and later reject non-default values on both API versions. And the older models are on a clock: claude-sonnet-4-5-20250929 retires on 30 November 2026, with claude-sonnet-5-5 as its replacement, and Sonnet 4.6 is listed as retiring no sooner than 17 February 2027.

Claude on Bedrock and Vertex AI

On Amazon Bedrock, SDK 2.x's AnthropicBedrock client sends 2026-10-21, which Bedrock only accepts for Claude 4.7 and later. An open SDK issue reports older models such as Sonnet 4.5, Opus 4.5 and Opus 4.6 answering with a different 400: Invalid API version: 2026-10-21. If you call those models on Bedrock, keep the Bedrock client on SDK 1.x until you move to a newer model.

On Google's Vertex AI, the version goes in the request body, and Anthropic says both vertex-2023-10-16 and 2026-10-21 are accepted.

What if you need temperature 0?

This is the real question. Plenty of teams set a low temperature for classification, extraction or anything that should give the same answer twice. No other setting replaces it. Anthropic's advice is to "use prompting to guide model behavior", and on models that support it, structured outputs are the closest thing to a consistency switch. You give Claude a JSON schema, and the response has to match it:

from typing import Literal

import anthropic
from pydantic import BaseModel

class Ticket(BaseModel):
    category: Literal["billing", "bug", "feature_request"]

client = anthropic.Anthropic()

response = client.messages.parse(
    model="claude-sonnet-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Classify this support ticket: ..."}],
    output_format=Ticket,
)
print(response.parsed_output.category)

messages.parse() turns the Pydantic model into a schema, sends it as output_config.format, and validates the reply. Two caveats from Anthropic's docs: the capitalization of enum values isn't guaranteed, and a reply that stops because of a refusal or the max_tokens limit may not match the schema. So keep a check after it.

Beyond that:

  • Put two or three worked examples in the prompt.
  • Check the output and retry on a mismatch, instead of hoping the model never produces one.
  • Don't reach for the old tricks. Prefilling the start of Claude's answer isn't supported on Claude 4.6 and later, and forcing a specific tool with tool_choice fails on some current models and settings (auto still works).

Put bluntly: if a pipeline only worked because temperature was 0, it was more fragile than it looked. Validation catches drift. A low temperature only made it rarer.

Catching it in code

The SDK retries rate limits and server errors, but a 400 fails straight away. Catch the typed error rather than matching message text:

try:
    message = client.messages.create(**params)
except anthropic.BadRequestError as e:
    # e.status_code is 400; log e.request_id for Anthropic support
    if any(k in e.message for k in SAMPLING_KEYS):
        params = request_params(params["model"], params)  # strip sampling keys, retry once
        message = client.messages.create(**params)
    else:
        raise

Other changes in the same release that can break things

The temperature change gets the attention, but 2026-10-21 has a few more:

  • The SDKs and the CLI now send your key as Authorization: Bearer <key> instead of X-Api-Key. The Claude API accepts either, but a proxy or gateway in the middle that only reads X-Api-Key will start rejecting your requests.
  • Passing two credentials to one client is now an error (a ValueError in Python, a TypeError in TypeScript).
  • Document blocks in assistant messages return a 400, and so do citations on text blocks in user messages.
  • Client-side compaction (compactionControl in TypeScript) is gone. Anthropic points to context_management instead.
  • The legacy Text Completions API is removed from the TypeScript, Go, Java and Ruby SDKs and the CLI.
  • The SDKs and CLI are now licensed under Apache 2.0 instead of MIT. No code changes are needed, but your legal team may want to know.

Read the full migration guide before you upgrade the SDK in production. It's long, but most of it is type renames you'll only notice at compile time.

Using Claude through Aight

Aight sells Claude Opus 5.5, Sonnet 5.5, Fable 5.1, Haiku 4.5 and a few older Claude models through one OpenAI-compatible API, at Anthropic's list prices. Sonnet 5.5 is $2 / $10 per million tokens, input / output, and Opus 5.5 is $4 / $20. The rule above applies there too: leave temperature and top_p out of Claude requests.

Where one key does help is the question that usually comes next: does another model handle this task better without a temperature knob? You can run the same prompts through Claude, GPT and Gemini on the same key and compare, with no new accounts:

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.getaight.ai/v1",
    api_key=os.environ["AIGHT_API_KEY"],
)

prompt = [{"role": "user", "content": "Classify this support ticket as billing, bug or feature request: ..."}]

for model in ["claude-sonnet-5-5", "gpt-5.6-terra", "gemini-3.1-pro-preview"]:
    reply = client.chat.completions.create(model=model, messages=prompt)
    print(model, "->", reply.choices[0].message.content)

Balance is prepaid in US dollars and doesn't expire. Recharges start at $5 plus a 3% processing fee, and each one adds 10% extra balance. The quickstart covers sign-up to first request.

If you've removed all three parameters and still get a 400, read the message again. The same release added a few other 400s, and the message names the field that caused it.


Sources

Checked on 31 October 2026.