GEMINI LABJP
SUNSET — gemini-robotics-er-1.6-preview shuts down on August 31. Twelve days out, there is not much room left to push the migration backMIGRATION — The replacement is Gemini Robotics ER 2, in public preview since July 30, with spatial reasoning, agentic code execution, and multi-step tool orchestrationPRICING — Gemini 3.7 Flash went GA on August 13 at $0.75 per million input tokens and $3.75 output, roughly half what Flash models have cost, holding through December 31, 2026PRICING — List prices double to $1.50 and $7.50 on January 1, 2027. Anything running across the new year deserves a two-stage estimate now rather than a surprise in JanuaryAVAILABILITY — Beyond the Gemini API and Google AI Studio, 3.7 Flash is live in Android Studio, Google Antigravity, and the Gemini Enterprise Agent PlatformDEPRECATION — The temperature, top_p, and top_k sampling parameters remain deprecated. If your code sets them explicitly, measure the output difference without them while there is still timeSUNSET — gemini-robotics-er-1.6-preview shuts down on August 31. Twelve days out, there is not much room left to push the migration backMIGRATION — The replacement is Gemini Robotics ER 2, in public preview since July 30, with spatial reasoning, agentic code execution, and multi-step tool orchestrationPRICING — Gemini 3.7 Flash went GA on August 13 at $0.75 per million input tokens and $3.75 output, roughly half what Flash models have cost, holding through December 31, 2026PRICING — List prices double to $1.50 and $7.50 on January 1, 2027. Anything running across the new year deserves a two-stage estimate now rather than a surprise in JanuaryAVAILABILITY — Beyond the Gemini API and Google AI Studio, 3.7 Flash is live in Android Studio, Google Antigravity, and the Gemini Enterprise Agent PlatformDEPRECATION — The temperature, top_p, and top_k sampling parameters remain deprecated. If your code sets them explicitly, measure the output difference without them while there is still time
Articles/API / SDK
API / SDK/2026-08-19Intermediate

gemini-2.5-flash Can Return a 404 'no longer available' While the Docs Still List No Shutdown Date

The shutdown date for gemini-2.5-flash is blank in the official deprecation table, yet 404 reports have been circulating since July. Here is why reading that column as a safety margin misleads you, and how to check your own keys.

Gemini API215Model DeprecationMigration2Error Handling3gemini-2.5-flash

I opened the Gemini deprecations page to plan the order of a migration, went looking for the gemini-2.5-flash row, and stopped at the shutdown column.

There is no date there. It says No shutdown date announced. Same for gemini-2.5-pro and gemini-2.5-flash-lite. The page was last updated on August 13, 2026.

Meanwhile, the developer forum has a thread from July 9 reporting that a call to gemini-2.5-flash came back with a 404 and the message This model models/gemini-2.5-flash is no longer available (thread). A separate report describes gemini-2.5-pro responding that it is no longer available to new users.

Blank shutdown date, failing calls. These two facts do not actually contradict each other. They only look like a contradiction if you read the shutdown column as a promise that the model stays up until that day.

An empty shutdown column is not the same as "still available"

Right above the tables, the deprecations page carries a note: the shutdown dates listed are the earliest possible dates on which a model might be retired, and the exact date will be communicated separately.

So the table gives you a floor, not a ceiling. Reading it as "we are fine until October 16" buys you confidence that nothing actually backs. And the dates for gemini-2.5-flash and gemini-2.5-pro that used to sit in those cells are now shown as unannounced. A date disappearing is not the same as a deadline moving further away.

Here is what I could read off the table as of the August 13 update.

ModelShutdown date in the docsRecommended replacement
gemini-2.5-proNot announcedNone listed
gemini-2.5-flashNot announcedNone listed
gemini-2.5-flash-liteNot announcedNone listed
gemini-2.5-flash-imageOctober 2, 2026gemini-3.1-flash-image-preview
gemini-2.0-flash / gemini-2.0-flash-001June 1, 2026 (already passed)gemini-3.6-flash

The row that unsettles me most is gemini-2.5-flash-image, whose recommended replacement is gemini-3.1-flash-image-preview. Read plainly, that asks you to move from a GA model to a preview one. If your policy is to keep preview models out of production defaults, you cannot simply follow it. The inversion I wrote about in the strongest Gemini being in preview while the cheap one is GA shows up on the deprecation side too.

"no longer available" and "no longer available to new users" are different failures

Two distinct messages appear in the reports, and the difference matters when you are isolating a problem.

The first one, no longer available, means the endpoint itself is closed. Any key should get the same answer.

The second one, no longer available to new users, depends on who is calling. Projects with a history of using that model keep working, while a project or key created more recently gets turned away. That asymmetry is the uncomfortable part.

As an indie developer looking after several apps and sites alone, I end up with one key per purpose, created at very different times. Production, staging, and scheduled jobs each have their own.

In practice it shows up like this: the long-lived production project works, but the staging project you spun up last month, or the key you minted for CI, returns a 404. Same code, same model ID, different outcome.

At that point every suspect looks like it lives in your code. You check the SDK version, you check the region, you re-read how the request is assembled, and the afternoon is gone. I have since moved one rule to the front of my checklist: when identical code behaves differently per environment, suspect the key before the code. If model availability is scoped per project, no amount of reading the request builder will produce an answer.

Find out what your own keys can see, in about five minutes

Stop guessing and call models.list once per key. If you would rather not add a dependency, curl is enough.

curl -s "https://generativelanguage.googleapis.com/v1beta/models?pageSize=200" \
  -H "x-goog-api-key: YOUR_API_KEY" \
  | grep -o '"name": "models/[^"]*"' \
  | sed 's|.*models/||; s|"$||' \
  | sort

If gemini-2.5-flash is missing from that list, the key can no longer see it, and the migration is no longer something you can leave for later.

Now the part that actually pays off. One key is not enough. Run it against production and against your CI or staging key, then diff the two. A model that only one side can see is a model that will eventually disappear from the other side as well.

#!/usr/bin/env python3
"""Compare models.list across a production key and a CI key, and print the difference."""
import json
import os
import sys
import urllib.request
 
ENDPOINT = "https://generativelanguage.googleapis.com/v1beta/models?pageSize=200"
 
 
def list_models(api_key):
    names = set()
    url = ENDPOINT
    while url:
        req = urllib.request.Request(url, headers={"x-goog-api-key": api_key})
        with urllib.request.urlopen(req, timeout=30) as res:
            body = json.load(res)
        for model in body.get("models", []):
            if "generateContent" in model.get("supportedGenerationMethods", []):
                names.add(model["name"].replace("models/", "", 1))
        token = body.get("nextPageToken")
        url = ENDPOINT + "&pageToken=" + token if token else None
    return names
 
 
def main():
    prod_key = os.environ.get("PROD_API_KEY")
    ci_key = os.environ.get("CI_API_KEY")
    if not prod_key or not ci_key:
        print("Set PROD_API_KEY and CI_API_KEY in the environment", file=sys.stderr)
        return 2
 
    prod = list_models(prod_key)
    ci = list_models(ci_key)
    only_prod = sorted(prod - ci)
    only_ci = sorted(ci - prod)
 
    print("Models visible to the production key: %d" % len(prod))
    print("Models visible to the CI key: %d" % len(ci))
    print("Production only:", ", ".join(only_prod) if only_prod else "none")
    print("CI only:", ", ".join(only_ci) if only_ci else "none")
    return 1 if (only_prod or only_ci) else 0
 
 
if __name__ == "__main__":
    raise SystemExit(main())

It filters on generateContent because mixing embedding and audio models into the same set makes the diff harder to read. It exits with code 1 when a difference exists, so you can drop it into a scheduled job and only hear from it on the days something moved.

Walking the pages properly matters more than it looks. Even with a generous pageSize, the catalog keeps growing, and there is no guarantee a single page holds everything.

Model IDs survive outside your code

Fixing the call sites was not the end of it. In my own repositories, the leftovers were mostly outside the code path.

grep -rInE 'gemini-(2\.0|2\.5)[a-z0-9.-]*' . \
  --include='*.py' --include='*.ts' --include='*.js' --include='*.kt' --include='*.swift' \
  --include='*.json' --include='*.yaml' --include='*.yml' --include='*.toml' --include='*.md'

Running that against my own repositories surfaced hits in places like these:

  • Default values in config files, where the code reads an environment variable but the fallback is still an old ID
  • Recorded test responses with an old model ID baked in, so the suite stays green no matter what the live endpoint does
  • Code samples written for readers, plus internal runbooks
  • App Store and Google Play descriptions, and feature pages that say in prose which model powers a feature

The second one is the quiet problem. A test replaying a recorded response says nothing when the real endpoint closes. I wrote about that shape from the freshness-gate side in green tests and dead production.

The fourth is not a technical break, but it keeps handing readers an outdated assumption. Adding one line to the migration checklist for searching prose, not just code, is cheap insurance.

The other date, so you do not choose a replacement twice

Choosing a replacement in a hurry usually means doing the same work again shortly afterward, because another date is already on the calendar.

gemini-3.7-flash reached general availability on August 13. The published introductory pricing of $0.75 per million input tokens and $3.75 per million output tokens runs through December 31, 2026, and the announced rate from January 1, 2027 is $1.50 / $7.50. Deciding on today's unit price alone means redoing the arithmetic in the new year.

So it saves effort to make the 2.5 migration decision alongside two questions:

  1. Which workloads hurt most if they stop right now? Conversational, batch, image, and embedding paths fail in very different ways.
  2. Will each workload still be running after January 2027, or does its job finish this year?

Work that finishes this year can take the introductory price at face value. Work that keeps running needs to be compared at the doubled rate, or you will migrate a second time in January. I worked through that trade-off from the rework-cost angle in routing between Gemini 3.7 Flash and 3.1 Pro by rework cost.

One more thing worth deciding in advance: how you treat the 404 once it starts arriving. A retired-model 404 is not the kind of failure that resolves if you wait. Stacking exponential backoff on top of it only accumulates time spent waiting for something that will never succeed. How that waiting failed to appear in the success-side statistics is covered in retrying a retired model never showed up in success latency.

If you do one thing today, call models.list with your production key and your CI key and compare the two lists. No difference means you can go back to watching the table for a while. A difference means you have a signal that arrived ahead of the official announcement.

Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

API / SDK2026-08-04
Retrying a Retired Model Never Showed Up in Success Latency
With the image generation models shutting down soon, I rebuilt a mock server to see what my retry layer actually does when it hits a retired model ID. The damage landed in wall time and queue wait, and never touched the metric I was watching.
API / SDK2026-08-18
Routing Between Gemini 3.7 Flash and 3.1 Pro by Rework Cost, Not Speed
A single question replaced my model-selection ritual: can a machine catch this output when it is wrong? Here is how that splits work between 3.7 Flash and 3.1 Pro, plus the pricing math across the December 31 cutover.
API / SDK2026-08-17
After generated_images Disappeared: Three Branches Between the Response and a Saved File
Once you switch to generate_content, the line that breaks is usually the save. Here are the three branches on the response side - zero image parts, a shifting image count, and picking the extension - plus a receiver function you can drop in.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →