OpenAI Shuts Down GPT-4, o1 and o3-mini on October 23: What Breaks in Your Code (It's Not Just the Model Name)

Typographic cover: the word OpenAI above a diff dated 2026-10-23, - model: 'gpt-4-turbo' in red and + model: 'gpt-5.6-sol' in green
Table of Contents

    On October 23, 2026 OpenAI shuts down gpt-3.5-turbo, gpt-4, gpt-4-turbo, o1, o1-pro, o3-mini, o4-mini, gpt-4.1-nano, one gpt-4o snapshot and gpt-image-1. The deprecations page makes the fix look like a string swap: put gpt-5.6-sol, -terra or -luna where the old name was. That swap is the easy part, and for a lot of code it isn’t even where the problem is.

    Four things break after you change the name, and one breaks in code where the name never appears: LangChain and LlamaIndex still default to gpt-3.5-turbo, so a project that never wrote a model name is using one that dies in 32 days. Below is everything, checked against OpenAI’s docs as they were served on September 21 and against the libraries’ source code. Where a claim comes from user reports rather than from OpenAI, I say so.

    If what you need is the full calendar across providers (Anthropic, Gemini, Azure) and how to tell whether a business chatbot is affected, that’s in the AI model retirements guide. This post is the code side.

    What shuts down, and what OpenAI says to use instead

    From the deprecations page, section “2026-04-22: Legacy GPT model snapshots”. OpenAI announced it by email on April 22; the substitute column was edited later, since it names models released in July. Prices are standard tier, per million tokens, input / output, from the pricing page:

    Shuts down Oct 23PriceSubstitutePriceChange
    gpt-3.5-turbo (-0125, -completions)$0.50 / $1.50gpt-5.6-terra$2 / $124× / 8×
    gpt-4 (-0613, -completions)$30 / $60gpt-5.6-sol$4 / $20cheaper
    gpt-4-turbo (-2024-04-09)$10 / $30gpt-5.6-sol$4 / $20cheaper
    gpt-4o-2024-05-13$5 / $15gpt-5.6-sol$4 / $20≈ / 1.3×
    gpt-4.1-nano$0.10 / $0.40gpt-5.6-luna$0.20 / $1.202× / 3×
    o1$15 / $60gpt-5.6-sol$4 / $20cheaper
    o1-pro$150 / $600gpt-5.6-sol, pro mode$4 / $20 + more tokenscheaper
    o3-mini$1.10 / $4.40gpt-5.6-sol$4 / $203.6× / 4.5×
    o4-mini$1.10 / $4.40gpt-5.6-terra$2 / $121.8× / 2.7×
    gpt-image-1$10 / $40 (image tokens)gpt-image-2$8 / $30cheaper

    Three details the table hides:

    • The gpt-4o alias is not on the list. It points to gpt-4o-2024-08-06 according to its model page, and only the May 2024 snapshot dies. gpt-4o-mini and gpt-4.1 (without -nano) aren’t on it either.
    • Sol’s $4 / $20 is a promotion. OpenAI says it is “available at least through November 21, 2026” and describes it as a 20% cut on input and 33% on output, which puts the regular price at about $5 / $30. Budget with that.
    • Fine-tunes go the same day: ft-gpt-3.5-turbo, ft-gpt-4, ft-gpt-4.1-nano-2025-04-14, ft-babbage-002 and ft-davinci-002. More on that below, because they have no real successor.

    What the failure looks like

    OpenAI’s only official statement is that “the model or endpoint will no longer be accessible.” It doesn’t document the error payload. What users reported after the July and August shutdowns this year (here and here) is consistent:

    404 invalid_request_error / model_not_found
    The model `gpt-5.1-codex` has been deprecated, learn more here:
    https://platform.openai.com/docs/deprecations
    

    The Python SDK raises it as openai.NotFoundError. Two practical consequences:

    1. It isn’t retryable. If your wrapper retries on any exception with backoff, on October 23 it will spend its retry budget on a request that can never succeed, and your users will wait for it. Retry on 429 and 5xx, not on 404.
    2. A health check that lists models will lie to you. According to those same reports, retired IDs keep showing up in GET /v1/models after they stop working. A startup check that confirms “my model is in the list” passes on a dead model. The only reliable check is a real one-token request.

    The Responses API words it differently (“Model not found …”), so if you match on the message text, match on code: model_not_found instead.

    1. The model you never wrote: library defaults

    This is the one that catches teams who think they are safe because grep gpt-3.5 finds nothing. I checked the source of the libraries that most tutorials from 2023 and 2024 use:

    LibraryDefault when you don’t pass a modelSource
    LangChain Python, ChatOpenAI"gpt-3.5-turbo"base.py#L733
    LangChain.js, ChatOpenAI"gpt-3.5-turbo"base.ts#L286
    LlamaIndex, OpenAI LLM"gpt-3.5-turbo", and it’s what core falls back to when no LLM is configuredDEFAULT_OPENAI_MODEL in llama-index-llms-openai
    Vercel AI SDKno default model, but openai.completion() “currently only” supports gpt-3.5-turbo-instructOpenAI provider docs

    So this, which appears in countless READMEs, is a gpt-3.5-turbo call:

    from langchain_openai import ChatOpenAI
    
    llm = ChatOpenAI(temperature=0)   # no model= → "gpt-3.5-turbo"
    

    And with LlamaIndex it can be less visible still: if you never set Settings.llm, a query engine builds an OpenAI() on its own, with the same default. LlamaIndex’s OpenAIResponses class defaults to gpt-4o-mini, which survives.

    The Vercel case has an earlier date: gpt-3.5-turbo-instruct shuts down September 28, together with babbage-002 and davinci-002, so anything using openai.completion() or the legacy /v1/completions endpoint has one week, not a month. Those three are the only models the endpoint’s reference still names.

    The fix is always the same: pass the model explicitly, and read it from configuration so the next shutdown is an environment variable, not a deploy.

    For contrast, laravel/ai 1.x already defaults to gpt-5.6-terra, -luna, -sol and gpt-image-2. Newer libraries got this right; the problem is code built on the ones from 2023.

    2. Tools on Chat Completions now need reasoning turned off

    Every substitute in the table is a reasoning model, and that changes the contract of Chat Completions. From the GPT-5.6 upgrade guide:

    For GPT-5.6, function tools in Chat Completions are compatible only with effective reasoning none. Reasoning with tools should use the Responses API.

    The default reasoning effort is medium. So a function-calling chatbot that worked on gpt-4-turbo, with the model string changed and nothing else, fails on its first request. This is the error one team hit on gpt-5.6-luna:

    400 - Function tools with reasoning_effort are not supported for gpt-5.6-luna
    

    You have two ways out. The minimal one keeps Chat Completions and turns reasoning off, which is the closest thing to how gpt-4-turbo behaved:

    const res = await openai.chat.completions.create({
      model: 'gpt-5.6-sol',
      reasoning_effort: 'none',     // required if you pass tools
      messages,
      tools,
    });
    

    The one OpenAI recommends is moving that call to the Responses API, where reasoning and tools do work together. It’s more than a rename: the system prompt goes to instructions, structured outputs move from response_format to text.format, and function definitions lose a nesting level:

    // Chat Completions
    tools: [{ type: 'function', function: { name: 'get_order', parameters } }]
    
    // Responses
    tools: [{ type: 'function', name: 'get_order', parameters }]
    

    The strictness default also flips. According to the migration guide, functions are non-strict by default in Chat Completions, while in Responses omitting strict makes it attempt strict mode. If your JSON schemas were written loosely, set strict explicitly instead of inheriting the new default.

    Chat Completions itself is not deprecated. OpenAI’s wording is that it “remains supported” and Responses “is recommended for all new projects”. You don’t have to migrate the endpoint on October 23, only decide about reasoning.

    3. max_tokens: renamed, and now it has to pay for thinking

    The Chat Completions reference marks max_tokens as “deprecated in favor of max_completion_tokens” and “not compatible with o-series models”. The docs don’t state whether GPT-5.6 rejects max_tokens outright; the team in the issue above reports that all their calls needed the new name. Rename it either way.

    The part that actually changes behavior is what the new parameter counts. max_completion_tokens covers “visible output tokens and reasoning tokens”, and reasoning tokens “are billed as output tokens” (reasoning guide). The classic gpt-3.5-turbo classifier with max_tokens: 50 to force a short label, moved to gpt-5.6-terra at its default medium effort, can spend the whole budget thinking and come back truncated or empty, and you pay for the reasoning anyway. OpenAI recommends reserving at least 25,000 tokens for reasoning and output.

    For short, deterministic tasks the fix is not a bigger budget but no reasoning:

    client.chat.completions.create(
        model="gpt-5.6-terra",
        reasoning_effort="none",        # a label doesn't need to think
        max_completion_tokens=50,       # was max_tokens
        messages=messages,
    )
    

    temperature and top_p are a similar trap. For GPT-5.2 and 5.4 the docs say they’re only supported with reasoning effort none; for 5.6 I couldn’t find the rule written down. If you pass them, test with and without reasoning before the 23rd instead of finding out in production.

    4. Fine-tuned models have no successor

    The substitute column sends ft-gpt-3.5-turbo to gpt-5.6-terra and ft-gpt-4 to gpt-5.6-sol. Those are base models. The GPT-5.6 model pages list fine-tuning as not supported, and from January 6, 2027 existing customers can no longer create fine-tuning jobs at all.

    In practice, whatever your fine-tune learned (tone, output format, domain labels) has to move into the prompt: few-shot examples, a strict schema through structured outputs, or retrieval. Plan that work now. It’s the only item on this list that is a project rather than a patch, and the training data you’ll need to write examples from is what you used to build the fine-tune.

    5. o1-pro and gpt-image-1: different parameters, not new names

    • o1-progpt-5.6-sol in pro mode. The guide is explicit: “do not search for or invent a separate gpt-5.6-pro slug”. Pro mode is a reasoning setting on Sol and only works through Responses, not Chat Completions. o1-pro was already Responses-only, so the endpoint doesn’t change; the model name and the reasoning setting do. OpenAI warns that pro mode “performs more model work”, so the per-token price is lower than o1-pro but the tokens per request go up.
    • gpt-image-1gpt-image-2. The image guide says to omit input_fidelity for gpt-image-2, so if your edit calls pass it, remove it. And if you depend on transparent backgrounds, gpt-image-2 has only offered them in preview since August 20.

    6. The bill

    For the GPT-4 family and o1, the switch saves money, even more so if you were still paying $30 / $60 for gpt-4-0613. For everything that was chosen because it was cheap, it costs more:

    • A classifier or router on gpt-3.5-turbo processing 1M input and 200K output tokens a day costs $0.80. On gpt-5.6-terra with reasoning off, $4.40. That’s 5.5× before counting a single reasoning token.
    • o3-minigpt-5.6-sol is 3.6× on input and 4.5× on output, and more once the promotion ends.
    • gpt-4.1-nanogpt-5.6-luna doubles input and triples output.

    If one of those lines matters to you, test a cheaper tier than the table suggests before accepting the substitute: the column says what OpenAI considers equivalent, not what your task needs. I break down per-task cost across providers in how much the OpenAI, Claude and Gemini APIs cost. And no, the table doesn’t point to gpt-6-astra, even though the reasoning guide now says “start with” it: at $10 / $50 and without temperature, top_p or top_logprobs it’s a different decision, which I cover in GPT-6 Astra for developers.

    The audit: three greps and a real request

    From the repository root. The first looks for the dead IDs as exact quoted strings, so it skips gpt-4o, gpt-4o-mini and gpt-4.1, which survive:

    # 1. Model IDs that die on Oct 23 (and Sep 28), as quoted strings
    grep -rnE "['\"\`](gpt-3\.5-turbo[a-z0-9-]*|gpt-4|gpt-4-0613|gpt-4-turbo[a-z0-9-]*|gpt-4-1106-preview|gpt-4o-2024-05-13|gpt-4\.1-nano[a-z0-9-]*|o1|o1-pro[a-z0-9-]*|o1-2024-12-17|o3-mini[a-z0-9-]*|o4-mini[a-z0-9-]*|gpt-image-1|babbage-002|davinci-002)['\"\`]" \
      --exclude-dir={node_modules,vendor,.git} .
    
    # 2. The same in environment files, where names go unquoted
    grep -rnE "=(gpt-3\.5|gpt-4(-|$)|o1|o3-mini|o4-mini|gpt-image-1$)" .env* 2>/dev/null
    
    # 3. Constructors that inherit a library default
    grep -rnE "ChatOpenAI\(|llama_index\.llms\.openai|openai\.completion\(" \
      --include=*.py --include=*.ts --include=*.js --exclude-dir=node_modules . | grep -v "model"
    

    The third one gives false positives by design (a multi-line constructor with model= on another line will appear), but the list is short and it’s worth reading it by eye.

    Then the test that counts: for every model you end up using, one real request with your production parameters (tools, max_completion_tokens, temperature if you pass it) against the new name. Not GET /v1/models, for the reason above.

    Model names in configuration also live outside the repo: Make, Zapier or n8n workflows, a vendor’s chatbot panel, a Google Sheet with a script. The retirements guide has the checklist for those.

    The rest of OpenAI’s calendar this year

    All from the same deprecations page:

    DateWhat shuts down
    Sep 24Videos API, sora-2 and sora-2-pro (no substitute)
    Sep 28gpt-3.5-turbo-instruct, babbage-002, davinci-002, gpt-3.5-turbo-1106
    Oct 1gpt-5.4-cybergpt-5.6-cyber (20 days’ notice)
    Oct 23Everything in this post
    Oct 31Evals go read-only
    Nov 30Evals dashboard and API, the v1/prompts API and reusable prompts, Agent Builder
    Dec 1gpt-image-1-mini, gpt-image-1.5, chatgpt-image-latestgpt-image-2
    Dec 11gpt-5, gpt-5-mini, gpt-5-nano, gpt-5-pro, o3 and o3-pro snapshots

    The last row deserves a note: the gpt-5 and o3 model pages each list only the snapshot being retired, so the aliases very likely die with them. The openai-php/laravel README still uses 'model' => 'gpt-5' as its example. The Assistants API was already shut down on August 26.

    Frequently asked questions

    Which OpenAI models shut down on October 23, 2026?

    gpt-3.5-turbo (including gpt-3.5-turbo-0125 and the -completions variant), gpt-4 and gpt-4-0613, gpt-4-turbo and gpt-4-turbo-2024-04-09, gpt-4-1106-preview, gpt-4o-2024-05-13, gpt-4.1-nano, o1, o1-pro, o3-mini, o4-mini and gpt-image-1, plus the fine-tuned models ft-gpt-3.5-turbo, ft-gpt-4, ft-gpt-4.1-nano, ft-babbage-002 and ft-davinci-002. OpenAI announced it on April 22, 2026. The gpt-4o alias, gpt-4o-mini and gpt-4.1 are not on the list.

    What should I replace gpt-4 and gpt-3.5-turbo with?

    OpenAI lists gpt-5.6-sol as the substitute for gpt-4, gpt-4-turbo, gpt-4o-2024-05-13, o1, o1-pro (in pro mode) and o3-mini; gpt-5.6-terra for gpt-3.5-turbo and o4-mini; gpt-5.6-luna for gpt-4.1-nano; and gpt-image-2 for gpt-image-1. They are reasoning models, so changing the name is not enough: tools in Chat Completions need reasoning_effort none, max_tokens becomes max_completion_tokens and counts reasoning tokens.

    What error does the OpenAI API return for a retired model?

    OpenAI does not document the payload. Users who hit the July and August 2026 shutdowns report HTTP 404 with type invalid_request_error and code model_not_found, raised by the Python SDK as openai.NotFoundError. It is not retryable. Retired IDs may keep appearing in GET /v1/models, so the only reliable check is a real request.

    Does LangChain still use gpt-3.5-turbo by default?

    Yes. As of September 2026, ChatOpenAI in both LangChain Python and LangChain.js defaults to gpt-3.5-turbo when no model is passed, and LlamaIndex's OpenAI LLM does too (it is also what LlamaIndex falls back to when Settings.llm is not set). Code that never names a model will fail on October 23. Pass the model explicitly.

    Why does gpt-5.6 fail with "Function tools with reasoning_effort are not supported"?

    Because in Chat Completions, GPT-5.6 only accepts function tools when the effective reasoning effort is none, and the default is medium. Either add reasoning_effort: none to the request, which behaves closest to gpt-4-turbo, or move the call to the Responses API, where tools and reasoning work together.

    Is the gpt-5.6 migration more expensive?

    It depends on what you had. From gpt-4, gpt-4-turbo or o1 it is cheaper: gpt-5.6-sol lists at $4 input and $20 output per million tokens, a promotional price available at least through November 21, 2026. From gpt-3.5-turbo to gpt-5.6-terra it is 4 times the input and 8 times the output price, and from o3-mini to sol about 3.6 and 4.5 times, before counting reasoning tokens, which are billed as output.

    What happens to my fine-tuned gpt-3.5-turbo model?

    It shuts down on October 23, 2026 with the base models. The listed substitute is the base gpt-5.6-terra, and GPT-5.6 does not support fine-tuning; from January 6, 2027 existing customers cannot create fine-tuning jobs. What the fine-tune learned has to move into the prompt: few-shot examples, structured outputs or retrieval.

    Found it useful? Share it

    Found it useful? Get the next one by email

    Once a week: what breaks when you upgrade, AI for developers and what I'm building, with sources. No spam.

    By subscribing you accept our privacy policy.

    Search

    Tags

    Migration AI PHP Laravel JavaScript Tutorial Web Development Upgrade Best Practices Security OpenAI SEO Backend Claude Laravel 13