◉GEMINI LABEN
●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り8日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り8日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…
記事一覧/API / SDK
◈ API / SDK/2026-09-12中級

10月2日に止まる gemini-2.5-flash-image の移行先は、公式表のままでは動きません

gemini-2.5-flash-image の停止は2026年10月2日です。ところが公式の推奨移行先として書かれている gemini-3.1-flash-image-preview は6月25日に停止済みでした。移行先を最後まで辿るスクリプトを書いて表の全行を検査し、同じ構造の行が11件あることを確かめた記録です。

Gemini API248画像生成13モデル移行15非推奨4Python51

9月の初め、手元の検証用スクリプトに残っていた gemini-2.5-flash-image を書き換えようとして、公式の Deprecations ページを開きました。該当の行には移行先がきちんと書かれておりましたので、その文字列をそのままコピーし、モデル ID の定数を差し替えました。

ところが差し替えた先の gemini-3.1-flash-image-preview は、同じページの別の表で、6月25日に停止済みと記されていたのです。

表の一行だけを見ていたら、止まるモデルから、すでに止まったモデルへ移るところでした。移行先は、書かれている一行ではなく、辿り着いた先で決まります。 その確かめ方を、実際に走らせた出力とあわせて書き残します。

10月2日の行が指していた移行先は、6月25日に止まっています

まず事実を並べます。Gemini deprecations の表から、関係する3行を抜き出しました。

モデル IDリリース停止日表に書かれた推奨移行先
gemini-2.5-flash-image2025年10月2日2026年10月2日gemini-3.1-flash-image-preview
gemini-3.1-flash-image-preview2026年2月26日2026年6月25日(停止済み)gemini-3.1-flash-image
gemini-3.1-flash-image2026年5月28日停止日の announce なし—

実際に移るべき先は、-preview の付かない gemini-3.1-flash-image のほうです。2026年5月28日に GA となり、停止日はまだ announce されていません。

gemini-2.5-flash-image は「Nano Banana」の名で広まった初代で、個人開発者のサンプルコードや記事にいちばん多く残っている画像生成のエンドポイントだと思います。私自身、作品や配信する素材の制作には AI を使っておりませんが、挙動の確認用に叩くコードは残しておりました。そういう「動いているから触っていない」コードほど、期限に気づかないのです。

もう一点、記事にするなら必ず添えるべき注記があります。公式は、表の停止日を「最も早い可能性のある日付」と明記しています。10月2日に必ず落ちると決まったわけではありませんし、正確な日付は事前に通知されるとも書かれています。慌てる必要はありませんが、期日として扱わない理由にもなりません。

移行先が生きているかどうかは、二つの欄で決まります

行を読むときに私が見ているのは、次の二つです。

  1. 停止日の欄が「No shutdown date announced」になっているか。日付が入っていれば、その移行先もいずれ書き換えが要ります。
  2. モデル ID に -preview が付いていないか。preview は GA より短い周期で入れ替わります。

gemini-3.1-flash-image-preview は、この両方に引っかかっていました。日付が入っていて、しかも preview です。それでも移行先の欄に書かれていたのは、行が announce された時点の情報のまま残っているからではないかと思います。表は行ごとに書かれ、あとから移行先の側が停止しても、その行が自動で追随するわけではないのでしょう。

つまり、表そのものが間違っているというより、一行だけでは完結しないつくりになっています。読み手の側で連鎖を辿る必要があります。

いま思えば、一行を読めば移行先が分かると思い込んでいたこと自体が、preview と GA の入れ替わりの速さを見くびっていたのかもしれません。

移行先を最後まで辿るスクリプト

手で辿ると見落としますので、短いスクリプトにしました。公式ページを保存したファイルを渡すと、停止日が announce されていないモデルに行き着くまで移行先を辿ります。標準ライブラリだけで動きます。

#!/usr/bin/env python3
"""Deprecations ページの「推奨移行先」を、生きているモデルまで辿る。
 
    python3 resolve_replacement.py deprecations.md
    python3 resolve_replacement.py deprecations.md gemini-2.5-flash-image
"""
import re, sys
from datetime import date, datetime
 
TODAY = date.today()
# | `model-id` | リリース日 | 停止日 | `推奨移行先` |
ROW = re.compile(
    r"\|\s*`?([a-z0-9.\-]+)`?\s*\|"   # モデル ID
    r"[^|]*\|"                        # リリース日(使いません)
    r"\s*([^|]*?)\s*\|"               # 停止日
    r"\s*`?([a-z0-9.\-]*)`?\s*\|"     # 推奨移行先
)
 
def parse_date(text):
    text = text.strip()
    if not text or "No shutdown" in text:
        return None                    # 停止日なし = 現時点では生きています
    for fmt in ("%B %d, %Y", "%b %d, %Y"):
        try:
            return datetime.strptime(text, fmt).date()
        except ValueError:
            continue
    return None
 
def load(path):
    table = {}
    with open(path, encoding="utf-8") as fh:
        for line in fh:
            m = ROW.search(line)
            if not m:
                continue
            model, shutdown_text, replacement = m.groups()
            if model in ("Model", "Preview models", "Deprecated models"):
                continue               # 表のヘッダと区切り行を落とします
            table[model] = {
                "shutdown": parse_date(shutdown_text),
                "replacement": replacement.strip() or None,
            }
    return table
 
def resolve(table, model, seen=None):
    seen = (seen or []) + [model]
    row = table.get(model)
    if row is None:
        return model, seen, "unknown"          # 表に載っていない ID
    if row["shutdown"] is None:
        return model, seen, "alive"            # ここが終点です
    nxt = row["replacement"]
    if not nxt or nxt in seen:                 # 移行先が空、または循環
        return model, seen, "dead-end"
    return resolve(table, nxt, seen)
 
def status_of(table, model):
    row = table.get(model)
    if row is None:
        return "表に載っていません"
    if row["shutdown"] is None:
        return "停止日なし"
    left = (row["shutdown"] - TODAY).days
    tail = "(停止済み)" if left <= 0 else "(あと %d 日)" % left
    return "停止日 %s%s" % (row["shutdown"].isoformat(), tail)
 
def main():
    table = load(sys.argv[1])
    targets = sys.argv[2:] or sorted(
        m for m, r in table.items() if r["shutdown"] and r["shutdown"] > TODAY
    )
    for model in targets:
        listed = (table.get(model) or {}).get("replacement")
        final, path, kind = resolve(table, model)
        print("%-42s %s" % (model, status_of(table, model)))
        print("  → 実際に移るべき先: %s (%s)" % (final, kind))
        if len(path) > 2:
            print("     経路: " + " → ".join(path))
        if listed and listed != final:
            print("  ⚠ 表の移行先 %s は %s" % (listed, status_of(table, listed)))
        print()
 
if __name__ == "__main__":
    sys.exit(main())

保存したページを渡して、問題の行だけを指定した結果です。

$ python3 resolve_replacement.py deprecations.md gemini-2.5-flash-image
gemini-2.5-flash-image                     停止日 2026-10-02(あと 20 日)
  → 実際に移るべき先: gemini-3.1-flash-image (alive)
     経路: gemini-2.5-flash-image → gemini-3.1-flash-image-preview → gemini-3.1-flash-image
  ⚠ 表の移行先 gemini-3.1-flash-image-preview は 停止日 2026-06-25(停止済み)

resolve() を再帰にしてあるのは、後で述べるとおり、連鎖が2段で終わらない行があったからです。

連鎖していたのは、画像モデルだけではありませんでした

同じスクリプトを表の全行に通しました。停止日が入っている行のうち、書かれた移行先と、辿り着いた終点が食い違うものが11件あり、そのうち 5件は移行先自体がすでに停止済みでした。

元のモデル表に書かれた移行先辿り着いた終点段数
gemini-2.5-flash-imagegemini-3.1-flash-image-preview(停止済み)gemini-3.1-flash-image2
gemini-2.5-flash-image-previewgemini-2.5-flash-image(10月2日)gemini-3.1-flash-image3
gemini-2.0-flash-preview-image-generationgemini-2.5-flash-image(10月2日)gemini-3.1-flash-image3
imagen-3.0-generate-002imagen-4.0-generate-001(停止済み)gemini-3.1-flash-image2
gemini-2.0-flash-litegemini-3.1-flash-lite(2027年5月7日)gemini-3.5-flash-lite2
gemini-robotics-er-1.5-previewgemini-robotics-er-1.6-preview(停止済み)gemini-robotics-er-2-preview2

画像生成まわりは3段の連鎖が二つありました。古いサンプルコードの gemini-2.0-flash-preview-image-generation から素直に辿ると、gemini-2.5-flash-image を経由して、ようやく gemini-3.1-flash-image に着きます。途中で止めると、20日後に止まるモデルに落ち着いてしまうわけです。

正直に書きますと、最初の版は11件ではなく16件を出しておりました。差の5件は誤検出です。停止日の欄が空の行——つまり、まだ止まる予定のないモデル——まで比較の対象にしていたためでした。gemini-3-flash-preview のように、停止日はないのに移行先だけが書かれている行があるのです。

判定の条件に「停止日が入っている行だけを見る」を足したところ、11件に落ち着きました。動くようになったコードより、条件を一つ足して減った件数のほうが、あとから読み返して役に立ちます。 減った理由をコメントに残しておくと、次に表の形が変わったときに自分を助けてくれます。

表を信じる前に、エンドポイントに聞く

ドキュメントは announce の記録で、実際に何が返ってくるかはエンドポイントが持っています。切り替える前に、使うつもりの ID が本当に配信されているかを一度だけ確かめる関数を、移行スクリプトの先頭に置いています。

from google import genai
 
client = genai.Client(api_key="YOUR_API_KEY")
 
def assert_served(model_id: str) -> None:
    """models.list に現れない ID は、その場で落とします。"""
    served = {m.name.removeprefix("models/") for m in client.models.list()}
    if model_id not in served:
        near = sorted(s for s in served if s.startswith(model_id.split("-preview")[0]))
        raise SystemExit(
            "%s は配信されていません。近い ID: %s" % (model_id, ", ".join(near) or "なし")
        )
 
TARGET = "gemini-3.1-flash-image"   # 表を辿って確定させた ID
assert_served(TARGET)               # ここを通れば、あとは差し替えるだけです

近い ID を並べて出しているのは、-preview を取り違えたときに気づけるようにするためです。私は取り違えましたので、この2行を足しました。

書き換え自体は、モデル ID を一箇所にまとめてあれば定数の差し替えで終わります。まとめていなければ、そちらが先の仕事になります。なお、SDK のメソッドが非推奨になる話と、モデルそのものが止まる話は別の期限です。ここは混同しやすいところですので、generate_images の非推奨とモデル停止では期限が違うという話にも書き残しております。

10月2日までの、今日の一手

やることは一つで足ります。手元のコードとドキュメントを gemini-2.5-flash-image で検索して、1件でも当たったら、移行先を表の一行ではなく終点まで辿ってください。 終点は gemini-3.1-flash-image です。

期限が近い順に並べておきます。9月30日に gemini-omni-flash-preview、10月2日に gemini-2.5-flash-image。この二つを過ぎると、次は2027年5月7日の gemini-3.1-flash-lite まで間が空きます。9月30日のほうは期限を一枚の表にまとめた記事に整理しております。

私はこの一件から、移行先の欄を読んだら必ずその行にも飛ぶ、という手順を自分に課しました。二度手間に見えますが、止まったモデルへ移して本番で気づくよりは、はるかに安い手間です。

最後までお読みくださり、ありがとうございました。皆さまの手元のコードが、10月2日を静かに通り過ぎますように。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

◈ API / SDK2026-10-08
停止日のない非推奨をどう扱うか — 画像モデルの移行先を、3つの条件で選び直す
10月6日に gemini-nano-banana-2.1 が GA になり、gemini-3.1-flash-image は停止日の書かれないまま非推奨になりました。解像度・参照画像・検索の3条件で移行先を選ぶ表と、確認用の短いスクリプトをまとめます。
◈ API / SDK2026-08-17
generated_images が消えたあとの受け取り方 — 戻り値から画像ファイルになるまでの3つの分岐
generate_content へ書き換えたあと、保存の行で落ちるのは戻り値の形が変わっているからです。画像 part が0件のとき・枚数が揺れるとき・拡張子を決めるときの3分岐と、そのまま使える受け取り関数をまとめます。
◈ API / SDK2026-08-15
generate_images は2027年まで残ります。それでも8月17日に画像生成は止まります
google-genai 2.18.1 には generate_images がまだ残っており、SDK の非推奨メッセージが指す期限は2027年です。一方で imagen-4.0 系のモデルは8月17日に止まります。2つの期限の違いと、手元で確認できること・できないことを実測で整理しました。