A row of weathered wooden stakes with pale bands stands in wet tidal sand at dusk, a lantern hanging from the nearest one, while driftwood and a small rowboat drift along curved currents
All posts

OpenAI GPT-4, o1, o3-mini and o4-mini shutdown on October 23, 2026: what breaks and what to check

OpenAI shut down GPT-4, o1, o3-mini, o4-mini and other models on October 23, 2026, so requests naming them now fail. Find the IDs left in fallbacks and jobs, then check each replacement's parameters, output and cost.

A migration that moved every primary call site off GPT-4, o1 and o3-mini can still leave failures behind: a retry fallback that names gpt-3.5-turbo, a nightly eval pinned to o3-mini, a fine-tuned gpt-4 ID stored in a database row. Those paths run rarely, so their first error can arrive well after the shutdown. OpenAI shut that wave down on 23 October 2026, as scheduled on its deprecations page, and every request naming one of its IDs now fails.

Search your code and configuration for each retired ID. Move every hit to the listed replacement (gpt-5.6-terra, gpt-5.6-sol or gpt-5.6-luna for the text models) once that replacement passes your own requests on parameters, output and cost. Then keep a lock file of the models you depend on, so the next retirement shows up in CI first.

Pinned exact IDs failed on 23 October too. A pinned snapshot stays fixed until its retirement date and then stops answering, so pinning trades a silent alias retarget for a date on the provider's schedule that you can plan around.

The 23 October wave and its listed replacements

OpenAI announced this wave on 22 April 2026. The table groups the models by the replacement the deprecations page recommends. The page lists each snapshot together with its undated aliases and -completions variants.

OpenAI models with a shutdown date of 23 October 2026, grouped by listed replacement
Listed replacementModels shut down
gpt-5.6-terragpt-3.5-turbo, o4-mini, and the fine-tuned ft-gpt-3.5-turbo, ft-o4-mini-2025-04-16, ft-babbage-002 and ft-davinci-002
gpt-5.6-solgpt-4, gpt-4-1106-preview, gpt-4-turbo, gpt-4o-2024-05-13, o1, o3-mini and the fine-tuned ft-gpt-4
gpt-5.6-sol with reasoning.mode: proo1-pro
gpt-5.6-lunagpt-4.1-nano and the fine-tuned ft-gpt-4.1-nano-2025-04-14
gpt-image-2.5-sunburst or gpt-image-2.5-flaregpt-image-1

Fine-tuned models went with their base models. The page names each fine-tuned family with an ft- prefix, such as ft-babbage-002, and gives it the same date and a recommended replacement base model, with no conversion path described. The IDs your code sends have a different shape, for example ft:babbage-002:my-org::abc123. To keep a fine-tuned model, train it again on the replacement base and re-qualify the result.

The wave listed the dated snapshot gpt-4o-2024-05-13. The undated gpt-4o, gpt-4o-mini and gpt-4.1 belong to a later wave that OpenAI announced on 14 October 2026: gpt-4o, gpt-4o-mini, gpt-4.1 and gpt-4.1-mini leave the API on 14 January 2027, with gpt-6-luna as the listed replacement. See how to migrate to GPT-6 Luna. o3 also retires later: its dated snapshot o3-2025-04-16 goes on 11 December.

Retired model IDs hide in fallbacks, defaults and scheduled jobs

The breakage that survives a first pass sits in retry and fallback lists, library and config defaults, eval and CI scripts, scheduled jobs, and fine-tuned model IDs stored in a database. A TheRouter summary of this wave tells readers to check primary models, fallback targets and per-team overrides. A Koenig AI Academy guide describes the failure: if a retry path still falls back to gpt-3.5-turbo, the primary model can be healthy while the fallback request fails.

This search finds the IDs in the table above, including dated snapshots, -completions variants and fine-tuned IDs in their ft: form:

rg -uu -nP '\b(?:gpt-3\.5-turbo(?:-0125)?|gpt-4(?:-0613|-1106-preview|-turbo(?:-2024-04-09)?)?|gpt-4\.1-nano(?:-2025-04-14)?|gpt-4o-2024-05-13|o1(?:-2024-12-17|-pro(?:-2025-03-19)?)?|o3-mini(?:-2025-01-31)?|o4-mini(?:-2025-04-16)?|gpt-image-1)(?:-completions)?(?![\w.-])|(?<=ft:)(?:babbage|davinci)-002(?![\w.-])' .

We ran it against a 37-line file. Twenty-six lines held retired IDs: every undated name and dated snapshot the pattern targets, a -completions variant, and six fine-tuned IDs such as ft:gpt-4-0613:acme::abc123 and ft:davinci-002:acme::abc123. The other 11 were controls that must not match: gpt-image-1.5, gpt-image-1-mini, gpt-4o, gpt-4o-mini, gpt-4.1, gpt-4.1-mini, o3, o3-2025-04-16, the base babbage-002 and davinci-002, and gpt-5.6-terra. The pattern matched all 26 retired lines and none of the controls.

The -uu flags also search git-ignored and hidden files such as .env, and dependencies, so expect noise from lockfiles. A default you do not own, for example inside a library under node_modules, is fixed by passing the model explicitly at the call site.

Then compare the hits with your request logs. The search shows which IDs exist in your code; the logs show which ones are still called and failing.

Each listed replacement changes price or parameters

The AIVAX catalog at https://inference.aivax.net/api/v1/information/models.json still carries o4-mini, o3-mini and gpt-4.1-nano. For those, the catalog prices and the model definitions in the product code show a change in price, in temperature support, or in both.

AIVAX catalog price (the representative price, not necessarily the provider's) in USD per million input / output tokens, as read on 2026-10-26, and whether the model definition rejects temperature, for each retiring model and its listed replacement
Retiring modelPriceRejects temperatureListed replacementPriceRejects temperature
@openai/o4-mini1.10 / 4.40Yes@openai/gpt-5.6-terra2.20 / 13.20Yes
@openai/o3-mini1.10 / 4.40Yes@openai/gpt-5.6-sol4.40 / 22.00Yes
@openai/gpt-4.1-nano0.10 / 0.40No@openai/gpt-5.6-luna0.22 / 1.32Yes

The prices are the catalog's representative price for each model, and the bill follows the provider that serves the request, so read providers[].pricing for the provider you route to and check the pricing page before you budget. Cost per task depends on token use as well as on the per-token price. The catalog lists thinking capability for all three replacements and for none of the retiring gpt-4.1-nano, so a move from nano to luna can change latency and token use along with the price. See how reasoning effort differs across providers for the controls that govern it.

The temperature columns come from the model definitions in the product code; the public catalog omits them. They matter for gateways, because the AI Gateway docs warn that some integrated models reject temperature. If a gateway set temperature on gpt-4.1-nano, expect to remove it when you point the gateway at gpt-5.6-luna, and re-qualify the output without it.

Tools are the other trap. On OpenAI Chat Completions, gpt-5.6-sol rejects function tools combined with a reasoning effort other than none, which older models accepted; see how to fix that error.

Qualify the replacement on frozen requests

Freeze a set of real requests and their accepted outputs, and run the candidate model against it. If the retired model already fails, build the set from logged requests and the outputs your users accepted before 23 October. Then compare the things that break quietly.

Start with parse and schema failures when a parser or schema sits behind the call, and see where structured-output healing stops before assuming the new model fails the same way. Request parameters come next, because models differ in what they accept. Anthropic's page says a non-default temperature, top_p or top_k returns a 400 from Claude Opus 4.7 onward, and the AIVAX gateway docs note that some integrated models reject assistant prefill, temperature, stop sequences or reasoning effort.

Tool calls and multi-turn behavior need their own run, because a single-turn comparison can miss a model that stops calling a tool several turns in. Agentic Tests run a simulated user and a judge against an AI Gateway, so create a second gateway with the replacement model and run the same scenarios against both. Run them alongside a single-turn regression set; the Agentic Tests docs list the quotas that apply.

Measure latency and cost per completed task on your own requests. A model that needs fewer retries can cost less per task at a higher token price, and our post on judging agent trajectories covers production signals for whole runs.

When the candidate passes, change the gateway or the pinned ID in one place, keep the old value in version control, and run the check again.

Should you pin a model ID or use an alias?

With an alias, the provider (or a router) decides, and nothing in your code changes when it does. With an exact ID, the target usually stays fixed until the retirement date, and after it requests fail. Anthropic's deprecation page puts it plainly: requests to models past the retirement date will fail. Google shows a third outcome. On 8 October the Gemini API deprecated gemini-3.5-flash and gemini-3.7-flash and, according to its changelog, routes requests that name them to gemini-3.6-flash and gemini-3.8-flash, so the exact ID keeps answering with a different model; the Google paragraph below has the details.

What each way of naming a model asks of you
NamingWho decides when behavior changesWhat you must doFits
Exact or dated IDYou, until the provider's retirement date, unless the provider reroutes the IDTrack the retirement date and run a replacement test before itParsers, budgets, customer-facing promises, regression baselines
Provider aliasThe provider, on its own scheduleDetect retargeting yourself; record what the alias resolved toPrototypes, internal helpers where a different answer costs little
Router alias (AIVAX @model-router/...)The platform, when it changes the alias targetRe-run your checks when the target changesTier-based choices where you accept movement within a tier
Gateway nameYou, by editing the gatewayQualify the new model before changing the gatewayMany clients that should switch together without a redeploy

A fixed snapshot prevents alias retargeting. Identical outputs and availability up to the retirement date stay outside that guarantee, and once a retirement date is announced, that date governs.

A provider alias, including a -latest name, can be acceptable in production when a changed answer is cheap, a human reads the output, and you record what the alias resolved to at the time. Use a fixed snapshot when accepting a new version requires regression testing. If you keep an alias, run the lock-file check described below every night so a retarget surfaces within a day.

Providers treat aliases and snapshots differently

The rules differ by provider and change between model generations, so read each provider's own page before inferring behavior from a model name.

At Anthropic, for the 4.6 generation and later, the dateless ID is the canonical ID and maps to one fixed snapshot, and Anthropic says it does not update the weights or configuration of an existing ID. For earlier models, a dateless alias such as claude-sonnet-4-5 points to the most recent dated snapshot of that minor version. Every ID, dated or not, has its own retirement schedule, and partner platforms such as Amazon Bedrock and Google Cloud set their own, so dates can differ there. See Model IDs and versioning and Model deprecations.

OpenAI lists the December 2026 removals on its deprecations page by dated snapshot, for example gpt-5-2025-08-07 and o3-2025-04-16. Our migration guide to GPT-5.6 Sol, Terra and Luna maps all six and prices the move. Check how the undated name behaves for your account before you rely on it.

Mistral's model lifecycle page warns that aliases switch to newer models automatically once they reach general availability, and recommends pinning a major.minor version for precise control.

Notice periods differ too. Anthropic promises at least 60 days for publicly released models. OpenAI's page lists gpt-5.4-cyber as deprecated on 11 September 2026 and removed on 1 October, and announced the April 2027 removals on 1 October 2026 with six months' notice.

Retirements announced after 23 October

Announced retirements after 23 October 2026 from the providers' own pages
DateModelListed replacement
2026-11-19Google Vertex AI gemini-3.6-flash (the Gemini API lists no date for it)gemini-3.8-flash
2026-11-30Anthropic claude-sonnet-4-5-20250929claude-sonnet-5-5
2026-12-01OpenAI gpt-image-1-mini, gpt-image-1.5 and chatgpt-image-latestgpt-image-2.5-sunburst or gpt-image-2.5-flare
2026-12-11OpenAI gpt-5-2025-08-07, gpt-5-mini-2025-08-07, gpt-5-nano-2025-08-07, gpt-5-pro-2025-10-06, o3-2025-04-16, o3-pro-2025-06-10gpt-5.6-sol, gpt-5.6-terra or gpt-5.6-luna, depending on the model
2027-01-06OpenAI tts-1, tts-1-hd and the gpt-4o-mini-tts snapshotsgpt-realtime-2.1-mini
2027-01-14OpenAI gpt-4o (gpt-4o-2024-08-06, gpt-4o-2024-11-20), gpt-4o-mini-2024-07-18, gpt-4.1-2025-04-14, gpt-4.1-mini-2025-04-14gpt-6-luna
2027-01-20OpenAI gpt-realtime, gpt-audio and their -mini and gpt-4o variantsgpt-realtime-2.1, gpt-realtime-2.1-mini or gpt-audio-1.5
2027-01-28Google Vertex AI gemini-3.7-flashgemini-3.8-flash
2027-02-26OpenAI whisper-1 and the gpt-4o transcription modelsgpt-transcribe or gpt-live-transcribe
2027-04-01OpenAI gpt-5.3-codex, gpt-5.4-nano, gpt-5.1gpt-6-sol or gpt-6-luna

If the 2027-01-20 row is your voice stack, the post on Realtime API interruptions covers the client-side truncation to retest after the switch.

Anthropic listed claude-haiku-4-5-20251001 as active, "not sooner than October 15, 2026": a minimum date, with no retirement scheduled. Google's deprecations page lists gemini-2.5-flash, gemini-2.5-flash-lite and gemini-2.5-pro with no shutdown date announced, and the Gemini API changelog says access to them is limited to users who already used them. Vertex AI disagrees: its model versions page lists all three as retired on 2026-10-20, so a date quoted for them belongs to Vertex, and the Gemini API gives none.

The Gemini 3.x Flash line shows the case where nothing fails. The Gemini API changelog entries of 8 October deprecate gemini-3.5-flash and gemini-3.7-flash, remove them from the Google AI Studio picker, and route API requests that name them to gemini-3.6-flash and gemini-3.8-flash. The deprecations page gives the old IDs no shutdown date ("N/A", with the note that the endpoint is not shutting down), so a health check still passes while a different model answers. Vertex does give the replacements dates: gemini-3.6-flash retires there on 2026-11-19 and gemini-3.7-flash on 2027-01-28, both with gemini-3.8-flash as the upgrade, while the Gemini API lists no date for gemini-3.6-flash.

AIVAX's public catalog marks @google/gemini-3.5-flash and @google/gemini-3.7-flash as deprecating, with no date, and does not mark @google/gemini-3.6-flash. On 28 October it lists the 3.5 ID at $1.50 input and $9.00 output per million tokens on its Google route, twice the $0.75 and $3.75 of the 3.6 ID. In the code I read, the model field of an AIVAX response carries the name you requested, so the response will not tell you which model Google served, and I do not know which rate applies to a call that names the old ID.

Legacy OpenAI user API keys were reportedly cut off on 22 October

One more cutoff fell the day before the model shutdown. An email from OpenAI, quoted in an OpenAI community thread, says legacy user API keys were deactivated on 22 October 2026. We found no page on OpenAI's own site that states this date, so confirm it against the email sent to your organization's owners. Several people in that thread could not find which of their keys were affected in the dashboard, so list your keys and replace any legacy key your services still use.

A dead key fails differently from a retired model. In the AIVAX code, a gateway that uses your own provider key (BYOK) passes every upstream error to the caller, including a 401, so a deactivated key surfaces as an explicit error.

AIVAX router aliases, explicit IDs and gateways change at different times

AIVAX lets you name what runs with an integrated model ID such as @openai/gpt-6-sol, a router alias such as @model-router/openai:mid, or a gateway name. They sit in different rows of the table above.

Router aliases move

The alias resolves to a concrete model, and the public changelog records these retargets. @model-router/openai:mid was pointed at GPT-6 Sol on 22 September and at GPT-6.1 Sol on 2 October; the 2 October entry also moved @model-router/claude:mid to Claude Sonnet 5.5. Each entry warns that applications using the aliases may see changes in response quality, latency and cost, and that existing explicit model identifiers remain unchanged.

Our routing guide covers when tier aliases are worth that movement. A retarget also changes the model behind your prompts, and a different model can have different caching behavior; see why a prompt cache hit rate is low.

Explicit IDs stay fixed until they are flagged and retired

The catalog flags some models as deprecated. On 2026-10-26 it flagged @openai/o3-mini, @openai/o4-mini and @openai/gpt-4.1-nano, which were in the 23 October wave. It also flagged models from later waves: @openai/gpt-5, @openai/gpt-5-mini, @openai/gpt-5-nano and @openai/o3 for 11 December, and @openai/gpt-4.1, @openai/gpt-4.1-mini, @openai/gpt-4o and @openai/gpt-4o-mini for 14 January 2027. Four more newer OpenAI models carry the flag as well (gpt-5.1, gpt-5.2-chat, gpt-5.3-codex and gpt-5.4-nano), and we did not look up their dates. The flag is AIVAX's catalog status and carries no date.

AIVAX can email an account that used a flagged model in the previous 30 days. The alert is on by default and sent at most once every seven days; check your account's notification settings before you rely on it.

We found no documented automatic substitution when a model is deprecated. Plan to change the model yourself, and record the provider's shutdown dates separately, from the pages above.

A gateway is one place to make the change

The AI Gateway docs describe a gateway as a persistent configuration that applications call by name, so its behavior can change without redeploying the caller. Clients keep calling the gateway while you qualify and change the model behind it.

An unavailable model is still an error your application must handle. In the code, resolving a gateway whose model name is no longer in the catalog throws "Couldn't resolve the model name".

The catalog and the provider's shutdown schedule are separate lists, so check both. With a gateway, you decide when the model changes, and you run the replacement test before it does.

Use a gateway when several clients must change together or when you want to switch without redeploying. Use an exact ID in code when one service owns its own behavior and tests. Either way, record the choice in a lock file.

Monitor alias targets and deprecation flags with a lock file

Keep a lock file of every integrated model ID and router alias your code or gateways use, plus the concrete model each router alias should resolve to. A CI job compares it with the live catalog at https://inference.aivax.net/api/v1/information/models.json, which answers without an API key.

For OpenAI models the provider date is also machine-readable: GET /v1/models returns an optional shutdown_date per model as a YYYY-MM-DD string, or null when no date is announced (List models). Alert on shutdown_date. Treat the AIVAX isDeprecating flag as a separate signal: catalog status, with no date attached.

The catalog endpoint is missing from the documentation, so treat its shape as unversioned. The script flags an entry when stability or flags is missing; it does not check that routingModel or isDeprecating exist, so a catalog that dropped them would pass silently.

{
  "@model-router/openai:mid": "@openai/gpt-6-sol",
  "@openai/gpt-6.1-sol": null,
  "@openai/o3": null,
  "@acme/retired-model": null
}
import { readFile } from "node:fs/promises";

const lock = JSON.parse(await readFile("models.lock.json", "utf8"));
const response = await fetch("https://inference.aivax.net/api/v1/information/models.json");
const { data } = await response.json();
const catalog = new Map(data.flatMap((group) => group.models).map((model) => [model.name, model]));

let failures = 0;

for (const [name, expectedTarget] of Object.entries(lock)) {
  const model = catalog.get(name);
  const problems = [];

  if (!model) {
    problems.push("not in catalog");
  } else {
    if (model.stability === undefined || model.flags === undefined) problems.push("unexpected catalog shape");
    if ([model.stability].flat().includes("Offline")) problems.push("offline");
    if (model.flags?.isDeprecating) problems.push("flagged as deprecating");
    if ((model.routingModel ?? null) !== expectedTarget) {
      problems.push(`resolves to ${model.routingModel ?? "nothing"}, expected ${expectedTarget ?? "nothing"}`);
    }
  }

  failures += problems.length > 0;
  console.log(`${problems.length ? "FAIL" : "ok  "} ${name}${problems.length ? ` (${problems.join("; ")})` : ""}`);
}

process.exit(failures ? 1 : 0);

When we ran bun check-models.js on 2026-10-05, this deliberately stale lock produced:

FAIL @model-router/openai:mid (resolves to @openai/gpt-6.1-sol, expected @openai/gpt-6-sol)
ok   @openai/gpt-6.1-sol
FAIL @openai/o3 (flagged as deprecating)
FAIL @acme/retired-model (not in catalog)

The exit code was 1. The stability field arrives as an array, which is why the script flattens it.

Run the check nightly and before each deploy, and run it more often if a retarget must be caught within hours. Change the lock deliberately, in a pull request, when you accept a retarget. This lock format holds only model targets or null, so track retirement dates and owners separately, for example in a calendar or an inventory next to each model's owner.

If something still fails after 23 October, start from the first table in this post. Run the rg pattern across repositories and gateway configurations, replace the hits one call at a time, and qualify each replacement before its new ID goes into the lock file.

Verification note

The 23 October model list matches OpenAI's deprecations page as read on 2026-10-23, and we ran the rg sample test the same day. The later retirement dates and Google's page (then last updated 2026-10-07) were read on 2026-10-07; the 14 January 2027 row was added on 2026-10-15, the day after OpenAI announced that wave. We read the AIVAX catalog again on 2026-10-26, and the prices and deprecation flags above come from that read. The deprecation email alert is described in the code and not in the public docs. We read it, the "Couldn't resolve the model name" error and the BYOK 401 pass-through in the code without triggering them. We did not reproduce the fallback failure that Koenig AI Academy describes, and did not send a request to test temperature on gpt-5.6-luna. Google's Gemini API pages (changelog, deprecations, pricing and the Gemini 3.5 Flash model page) and the Vertex AI model versions page were read on 2026-10-28, and the AIVAX prices for the Gemini IDs come from the public model catalog the same day. We did not call a Gemini ID to see which model answers or what it is charged.