GEMINI LABJP
VIDEO — Agentic video understanding reached 3.7 Flash, 3.6 Flash, and 3.5 Flash-Lite on September 1. The model navigates the timeline itself rather than sampling frames at a fixed rateTOKENS — Because it pulls transcripts, frames, or audio only when it needs them, Google measures up to 88% fewer tokens on long-form contentSCOPE — It works across both the Interactions and GenerateContent APIs. If you have costed out long-video work before, the assumptions have movedMUSIC — Lyria 3.5 entered public preview on September 3, generating full-length songs at 44.1 kHz stereoCONTROL — Lyria 3.5 accepts text and image inputs, with better musical coherence, more natural vocals, and finer control over duration and structureROBOTICS — gemini-robotics-er-2-streaming-preview is tuned for real-time streaming over the Live API, with function calling that blocks on physical robot actionsVIDEO — Agentic video understanding reached 3.7 Flash, 3.6 Flash, and 3.5 Flash-Lite on September 1. The model navigates the timeline itself rather than sampling frames at a fixed rateTOKENS — Because it pulls transcripts, frames, or audio only when it needs them, Google measures up to 88% fewer tokens on long-form contentSCOPE — It works across both the Interactions and GenerateContent APIs. If you have costed out long-video work before, the assumptions have movedMUSIC — Lyria 3.5 entered public preview on September 3, generating full-length songs at 44.1 kHz stereoCONTROL — Lyria 3.5 accepts text and image inputs, with better musical coherence, more natural vocals, and finer control over duration and structureROBOTICS — gemini-robotics-er-2-streaming-preview is tuned for real-time streaming over the Live API, with function calling that blocks on physical robot actions
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 API234Model DeprecationMigration4Error 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 $15 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-09-02
Taking stock of Gemini standard API keys before September, across CI, servers, and my own machine
Standard API keys, including restricted ones, stop being accepted during September. Because this changes where keys come from rather than what they say, here is the three-layer inventory I ran across code, deploy settings, and my local machine, plus a dual-path client to switch behind.
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-09-07
The day Lyria 3.5 landed, I changed how my audio folders are laid out
When Lyria 3.5 brought full-length generation, my generated takes were sitting in the same folder as the tracks I had chosen by hand. Here is the forty-line ledger gate that draws the line by hash, not by filename.
📚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