Blog

OpenAI "model not found" after the 23 October shutdowns: what replaced o4-mini, gpt-4.1-nano and the rest

Ramashankar S · · Updated · 12 min read

If your app started throwing 404s on Friday, 23 October, check the model name before you check anything else.

That day OpenAI switched off a long list of older models: gpt-3.5-turbo, gpt-4, gpt-4-turbo, o1, o1-pro, o3-mini, o4-mini, gpt-4.1-nano, the May 2024 snapshot of gpt-4o, and gpt-image-1. Fine-tuned versions of those models went with them.

None of this was secret. OpenAI posted the notice on 22 April. But six months is plenty of time to forget about a model ID sitting in a cron job, and judging by the forum threads, a lot of people did.

This post covers what replaced each model, how to find every place you still call one, what the switch does to your bill (for some of you it goes up), and the settings that break a second time after the rename.

What the error looks like

A request to a retired model comes back as HTTP 404 with a body like this:

{
  "error": {
    "message": "The model `o4-mini` does not exist or you do not have access to it.",
    "type": "invalid_request_error",
    "param": null,
    "code": "model_not_found"
  }
}

The annoying part: OpenAI uses the same model_not_found code for a retired model, a typo in the model ID, and a model your organization isn't allowed to use. So before you dig through billing or permissions, look at the model name in the failing request. If it's in the table below, you've found your problem.

The status code helps tell the cases apart. A retired or misspelled model returns a 404. Developers who run into a project's model allowlist report a 403 with the same model_not_found code and a message along the lines of "Project ... does not have access to model ...". That model exists, and a project admin has to allow it.

OpenAI's error guide doesn't publish the exact wording of these messages, so branch on the status and the code field in your code, not on the text.

Every retired model and its replacement

This comes straight from OpenAI's deprecations page. Prices are OpenAI's list prices per million tokens, input / output, from its pricing page.

Retired modelOpenAI's replacementOld priceNew price
gpt-3.5-turbogpt-5.6-terra$0.50 / $1.50$2.00 / $12.00
gpt-4gpt-5.6-sol$30.00 / $60.00$4.00 / $20.00
gpt-4-turbo, gpt-4-1106-previewgpt-5.6-sol$10.00 / $30.00$4.00 / $20.00
gpt-4o-2024-05-13gpt-5.6-sol$5.00 / $15.00$4.00 / $20.00
gpt-4.1-nanogpt-5.6-luna$0.10 / $0.40$0.20 / $1.20
o1gpt-5.6-sol$15.00 / $60.00$4.00 / $20.00
o1-progpt-5.6-sol, with reasoning.mode: pro$150.00 / $600.00$4.00 / $20.00
o3-minigpt-5.6-sol$1.10 / $4.40$4.00 / $20.00
o4-minigpt-5.6-terra$1.10 / $4.40$2.00 / $12.00
gpt-image-1gpt-image-2.5-sunburst or gpt-image-2.5-flarenot listed$5 text in, $8 image in, $30 image out

A few details that cause confusion:

  • The dated snapshots went too, so o4-mini-2025-04-16 and gpt-4-0613 are gone along with their short names.
  • Only the May 2024 gpt-4o snapshot was retired. Plain gpt-4o and its later snapshots keep working until 14 January 2027.
  • The gpt-5.6-sol price is a promotion. OpenAI says it runs "at least through November 21, 2026", so plan for it changing.
  • o1-pro has no separate Pro model now. You keep gpt-5.6-sol and set reasoning.mode to pro, which only works in the Responses API. Pro mode is billed at Sol's normal token rates, but it does more work per answer, so expect more tokens per request.

If you haven't looked at the GPT-5.6 family yet, OpenAI's own introduction is short:

Sol, Terra and Luna: the GPT-5.6 model familyOpenAI · 3:27 · YouTube
OpenAI's three-minute introduction to the family that replaced most of the retired models.

Some of you just got a price increase

Retired OpenAI models grouped by whether the suggested replacement costs less or more

If you were on gpt-4, gpt-4-turbo or o1, good news. Moving gpt-4 traffic to gpt-5.6-sol cuts input cost from $30 to $4 per million tokens.

The small models go the other way. gpt-4.1-nano to gpt-5.6-luna doubles the input price and triples the output price. o4-mini to gpt-5.6-terra nearly triples output. And anyone still running gpt-3.5-turbo is looking at 8x more per output token on terra.

The replacements OpenAI names aren't your only option, and they aren't the lowest-priced ones either. Its newer models undercut them:

Output price per million tokens: the retired model, OpenAI's named replacement, and a newer model that costs less
Instead ofTryPrice
gpt-5.6-terra ($2 / $12)gpt-6.1-terra$1.00 / $5.00
gpt-5.6-sol ($4 / $20)gpt-6.1-sol$2.00 / $10.00
gpt-5.6-luna ($0.20 / $1.20)gpt-6-luna$0.10 / $0.50

Check two things before you switch. The 6.1 models only do tool calling through the Responses API, not Chat Completions. And gpt-6.1-sol doesn't accept a reasoning effort of none. If your old code calls functions through Chat Completions, gpt-6-luna or the 5.6 family is the shorter move. And if the work can wait up to a day, the Batch API halves all of these prices.

Whichever you pick, don't just paste in a model name and move on. Run a few hundred of your real prompts through two candidates and compare. A lower price doesn't help if the model gets 2% more answers wrong. That can still cost you more.

Find every place that still calls a retired model

Renaming is quick. Finding every caller is the slow part.

Start with the API. The List models endpoint now returns a shutdown_date for any model that has one, so this prints every model your key can reach that has a date set, soonest first:

curl -s https://api.openai.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  | jq -r '.data[] | select(.shutdown_date) | "\(.shutdown_date)  \(.id)"' | sort

Then find the callers. The Usage API breaks token use down by model and by API key, so you can see which key, and so which service, was calling o4-mini or gpt-4.1-nano. It needs an admin key. This asks for daily totals from 1 October (1790812800 in Unix time), the weeks when those models were still in use:

curl "https://api.openai.com/v1/organization/usage/completions?start_time=1790812800&bucket_width=1d&limit=31&group_by=model&group_by=api_key_id" \
  -H "Authorization: Bearer $OPENAI_ADMIN_KEY"

Then check the places a code search misses:

  • Batch input files. Each file can only contain requests to one model, so a batch job built for gpt-3.5-turbo needs a regenerated input file, not just a new job.
  • Saved prompts. A request can pass a saved prompt ID (pmpt_...) with no model in your code at all, because the model is stored with the prompt in the dashboard. The v1/prompts API itself shuts down on 30 November 2026, so move that prompt text into your code while you're there.
  • Env files, scheduled jobs, eval scripts, framework defaults, and the notebook a teammate runs on Mondays.

The fix

Mostly, you change the model name:

from openai import OpenAI

client = OpenAI()

response = client.chat.completions.create(
    model="gpt-5.6-terra",   # was "o4-mini", which now returns 404
    messages=[{"role": "user", "content": "Summarize this support ticket in one line."}],
)
print(response.choices[0].message.content)

What else changes when you switch

The new models aren't copies of the old ones with new names. Four differences cause most of the second round of errors:

  • GPT-5.6 models reason before they answer, and if you don't set a reasoning effort, they use medium. gpt-3.5-turbo, gpt-4 and gpt-4.1-nano had no reasoning step, so a straight swap makes simple calls slower and adds reasoning tokens to the bill. For classification, extraction or short replies, start at none or low and raise it only if quality needs it.
  • max_tokens is deprecated in favor of max_completion_tokens, and the new limit counts reasoning tokens too. A tight limit that suited gpt-3.5-turbo can run out during reasoning, before any visible text is produced. You pay for the reasoning and get an empty answer.
  • OpenAI recommends the Responses API for reasoning, tool calling and multi-turn work on GPT-5.6. On gpt-6-luna and gpt-6-sol, function calling through Chat Completions only works with reasoning_effort: "none".
  • On the GPT-6 models, OpenAI says to remove temperature, top_p and top_logprobs whenever reasoning effort isn't none.

For a simple task moving off gpt-3.5-turbo, that looks like this:

response = client.chat.completions.create(
    model="gpt-5.6-terra",
    reasoning_effort="none",      # GPT-5.6 defaults to "medium"
    max_completion_tokens=300,    # replaces max_tokens, and includes reasoning tokens
    messages=[{"role": "user", "content": "Classify this ticket as billing, bug or feature request: ..."}],
)

If you rely on prompt caching, check those numbers too. Writing to the cache on GPT-5.6 costs 1.25x the normal input rate, so watch cached_tokens and cache_write_tokens in the usage data to see what you actually save.

For a longer walk through choosing between Sol, Terra and Luna, and moving tool schemas and caching across, OpenAI's Build Hour on GPT-5.6 is worth the time. It was recorded in July, so check any prices in it against the pricing page.

Build Hour: Valuemaxxing with GPT-5.6OpenAI · 54:33 · YouTube
OpenAI's hour-long session on picking a GPT-5.6 model by cost and latency.

Add a fallback while you're in there

A tested fallback turns the next shutdown into a log line instead of an outage. The OpenAI SDK retries timeouts, rate limits and server errors on its own, but not a 404 or a 403, so catch those yourself:

import logging
from openai import OpenAI, NotFoundError, PermissionDeniedError

client = OpenAI()
MODELS = ["gpt-5.6-terra", "gpt-6-luna"]  # first choice, then a fallback you've tested

def complete(messages):
    for model in MODELS:
        try:
            return client.chat.completions.create(model=model, messages=messages)
        except (NotFoundError, PermissionDeniedError) as e:
            if e.code != "model_not_found":
                raise
            logging.warning("%s is unavailable, trying the next model", model)
    raise RuntimeError("no model in MODELS is available")

Pick the fallback with the calendar in mind. gpt-5, gpt-5-mini, gpt-5-nano, gpt-5-pro, o3 and o3-pro all shut down on 11 December, so none of them is a safe choice.

Fine-tuned models

A fine-tune of a retired model is retired with it, and training a new one isn't the easy way out it used to be. OpenAI is winding down its fine-tuning platform. It's closed to new users, and existing customers can create training jobs until 6 January 2027, or until the base model shuts down if that's earlier. For most teams the practical replacement is a current model with a handful of good examples in the prompt, checked against the old fine-tune's outputs.

On Azure? Different dates, different error

Azure OpenAI runs its own schedule, so OpenAI's list doesn't apply directly. When an Azure model version retires, requests return 410 Gone instead of a 404. The dates differ too:

  • o1, o1-pro, o3-mini and o4-mini retire on Azure on 19 November 2026, almost a month after OpenAI.
  • gpt-4o version 2024-05-13 retires on 14 January 2027. Global Standard and Data Zone Standard deployments of it upgrade automatically to gpt-5.1 (2025-11-13), not to a GPT-5.6 model.
  • gpt-4.1-nano stays on Azure until 14 April 2027.

Check Microsoft's retirement schedule, not OpenAI's.

The next shutdowns

More are coming. OpenAI's policy promises at least six months' notice for generally available models, but don't plan around that. The 14 January shutdown of gpt-4o and gpt-4.1 was announced on 14 October, three months ahead.

OpenAI shutdowns from November 2026 to April 2027, with replacements
DateShutting downOpenAI's replacement
30 Nov 2026v1/prompts API and saved prompt objectsPrompt text in your own code
1 Dec 2026gpt-image-1.5, gpt-image-1-mini, chatgpt-image-latestgpt-image-2.5-sunburst or gpt-image-2.5-flare
11 Dec 2026gpt-5, gpt-5-mini, gpt-5-nano, gpt-5-pro, o3, o3-progpt-5.6-sol, terra or luna
6 Jan 2027tts-1, tts-1-hd, gpt-4o-mini-ttsgpt-realtime-2.1-mini
14 Jan 2027gpt-4o, gpt-4o-mini, gpt-4.1, gpt-4.1-minigpt-6-luna
26 Feb 2027whisper-1, gpt-4o-transcribe, gpt-4o-mini-transcribegpt-live-transcribe or gpt-transcribe
1 Apr 2027gpt-5.1, gpt-5.3-codex, gpt-5.4-nanogpt-6-sol, or gpt-6-luna for nano

Three things worth doing now, while it's still quiet:

  1. Keep model IDs in config, not in code. One setting per job means one change per migration.
  2. Give every job a fallback model that you've actually tested, like the snippet above.
  3. Run the shutdown_date check from earlier once a week in CI, and alert when a model you call gets a date. That beats remembering to read the deprecations page.

Where Aight fits

Aight is one OpenAI-compatible API for 126 models from OpenAI, Anthropic, Google, xAI, DeepSeek and others. The text replacements above (gpt-5.6-luna, gpt-5.6-terra, gpt-5.6-sol), plus gpt-6-luna and gpt-6.1-sol, are on it at OpenAI's list prices, so you can test them side by side with Claude or Gemini on the same key.

If you already use the OpenAI SDK, switching is two lines:

import os
from openai import OpenAI

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

A few things that help in a week like this one:

  • Each key can have a list of allowed models. A forgotten script can't quietly call something you didn't plan for, because anything outside the list gets a 403.
  • Aight gives at least 14 days' notice before it removes a model, where the provider allows, and names a replacement.
  • Balance is prepaid in US dollars and doesn't expire. Recharges start at $5 plus a 3% processing fee, and every recharge adds 10% extra balance.

The quickstart covers sign-up to first request in four steps.

One last thing. If you've switched the model and still see 404s, search for the old name again. It's nearly always hiding in one more place.


Sources

Prices and dates checked on 31 October 2026.