I was counting the lines that mention claude-sonnet-4-5 across my own code samples and notes when something odd came up.
The retirement table lists claude-sonnet-4-5-20250929, with a date attached. But most of what I had written down was the undated form. The count was 69 places without a date and 61 with one.
My first thought was that I'd never typed the date, so the table's "November 30" probably wasn't about me. I wasn't sure that thought would survive a second look, so I went back to the docs. Here is what I found.
The table only lists the dated ID
On the model deprecations page, the relevant rows read like this today.
| API model name | Current state | Deprecated | Tentative retirement date |
|---|---|---|---|
| claude-sonnet-4-5-20250929 | Deprecated | September 30, 2026 | November 30, 2026 |
| claude-sonnet-4-6 | Active | N/A | Not sooner than February 17, 2027 |
The recommended replacement is claude-sonnet-5-5. There is no row for the undated claude-sonnet-4-5, which makes "not listed, so not affected" a tempting reading. That reading was my mistake.
An undated ID can be an alias for the latest dated one
The "Model IDs and versioning" page gets closer to an answer. For models before the 4.6 generation, the Claude API also accepts shorter aliases. claude-sonnet-4-5, for example, points to the most recent dated snapshot of that minor version.
So claude-sonnet-4-5 isn't a separate model. It's a shortcut to claude-sonnet-4-5-20250929. The same page also says every model ID has its own deprecation and retirement schedule.
Here is how I sorted it out.
| What you wrote | What the docs say | Relation to November 30 |
|---|---|---|
| claude-sonnet-4-5-20250929 | A dated snapshot | The row in the table. Affected |
| claude-sonnet-4-5 | An alias for the latest dated snapshot | It points at 20250929, so it is natural to expect it to stop the same day |
| claude-sonnet-4-6 | Undated, but not an alias. It is the snapshot itself | A different ID. The table gives February 17, 2027 as the earliest date |
The "stops the same day" part is my own inference from how aliases work. I haven't seen the docs say it in one sentence. So I decided to treat the alias as affected rather than bet that it's exempt.
One more trap: from the 4.6 generation on, an undated ID such as claude-sonnet-4-6 is not an alias. The docs say plainly that it is a pinned snapshot, not an evergreen pointer that moves to newer versions. Having no date doesn't mean being newer.
One grep for both forms
If you search only for the dated string, aliases slip through. A single pattern covers everything.
# Dated, undated, and the Bedrock / Google Cloud spellings in one pass
grep -rnE --exclude-dir=node_modules --exclude-dir=.git \
'claude-sonnet-4-5(-20250929|@20250929|-v1:0)?' .On Amazon Bedrock the ID appears as anthropic.claude-sonnet-4-5-20250929-v1:0, and on Google Cloud (Google managed) as claude-sonnet-4-5@20250929. The pattern above catches all three. Note that those partner platforms set their own retirement schedules, so the November 30 date in the table applies to the platforms Anthropic operates. Keep that boundary in mind.
Then sort the hits into config files and prose. Only the lines that actually send requests can break anything.
If you're unsure, let the response tell you
You can see what an alias resolves to by sending one small request. The model field of the response carries the resolved ID.
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from the environment
msg = client.messages.create(
model="claude-sonnet-4-5", # send the alias
max_tokens=16,
messages=[{"role": "user", "content": "Reply with ok"}],
)
print(msg.model) # the resolved ID shows up hereIf a dated ID comes back, you know where the alias points. I decided to run this once before touching anything.
One thing to settle before you replace anything
Before rewriting every hit mechanically, separate the lines that really send requests. Grep alone can miss callers. I wrote up a way to count them from the Usage CSV in 43 Days Until Sonnet 4.5 Retires: I Counted Callers From the Usage CSV, Not From grep. And if you plan a bulk replace, Read the Catalog Your CLI Already Ships Before Bulk-Replacing Model IDs covers the step before it.
Count by the ID a name resolves to, not by whether it carries a date. That's the line I'm drawing this time.
Run the grep above once today and just count the undated lines. About three weeks remain, and once you have the number, the rest of the plan tends to fall into place.