◉GEMINI LABEN
●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り5日。移行先は 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 に停止、残り5日。移行先は 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-10-19中級

404 と 429 が同じログに並んだら、上限より先にモデル名を確かめます

Gemini API のログに 404 NOT_FOUND と 429 RESOURCE_EXHAUSTED が混ざって出たとき、どちらから疑うかの順番と、生成を伴わずに切り分ける最小の Python スクリプトをまとめます。

gemini-api289troubleshooting62404429model-not-foundpython108

フォーラムで、ある Android アプリの投稿を読みました。回路図の写真を Gemini に読ませるアプリで、画面には「モデルが見つかりません。設定のモデル名を確認してください」と出ます。ところが Logcat を開くと、404 NOT_FOUND と 429 RESOURCE_EXHAUSTED が同じ画面に並んでいる、という内容でした。投稿者は、モデル名の誤り、API バージョン、上限、キー、リトライ処理のどれが本命なのか、決めかねておられました。

私はこの投稿に答えが付いているかを確かめに行き、付いていないことを知りました。そして読み返しているうちに、自分の書く呼び出しも、条件が重なれば同じ並びのログを出しうる、と気づきました。個人開発で壁紙アプリの画像分類に Gemini を使っている私自身にとっても他人事ではありません。そこで今日は、答えを推測で書く代わりに、切り分けの順番だけを決めておくことにします。

最初にお伝えしたいのは、404 と 429 は別々の問いだということです

公式のエラー一覧では、404 は not_found と model_not_found、429 は rate_limit_exceeded と quota_exceeded と too_many_requests に分かれています。同じ画面に並んでも、問われている中身は違います。

見えた症状問われていること待てば直るか
404 model_not_foundこのキーから、その名前のモデルが見えているか直りません。名前か利用者の条件を直します
429 rate_limit_exceeded短い時間に投げすぎていないか待てば通ります
429 quota_exceeded今日の枠を使い切っていないか枠が戻るまで通りません

ここで私が引いた線は一つです。名前が通っていない呼び出しの 429 は、上限の話として読まないようにしています。 名前の問題を片づける前に上限を調べ始めると、見ているグラフがそもそも別の原因を指しているかもしれません。

なぜ両方が同時に出るのか——確かめられたことと、そうでないこと

正直にお伝えします。先ほどのスレッドには、原因を確定した返信がありませんでした。ですので「モデル名の誤りが偽の 429 を作る」とは、私には書けません。

言えるのは次の二点です。一つは、アプリが失敗のたびに別のモデルへ落とす設計だと、1回の操作で複数のリクエストが出ること。もう一つは、その複数のリクエストが、それぞれ別の理由で失敗しうることです。たとえば本命のモデル名が古くて 404、フォールバック先は実在して、短時間に束ねて投げたぶん 429、という並びは、片方のログだけ見ると矛盾して見えます。

そうであれば、見るべきは「どのリクエストが、どのモデル名で、どのコードを返したか」の対応表です。件数ではなく、行ごとの対応です。

生成を打たずに、名前だけを先に確かめます

モデル名の存在は、生成を伴わない models.get で見られます。上限を消費する操作ではないので、429 に当たっている最中でも、状況を悪化させずに打てます。次のスクリプトは、名前→上限の順で分類します。

import json, urllib.request, urllib.error
 
BASE = "https://generativelanguage.googleapis.com/v1beta"
 
def call(path, key, body=None):
    req = urllib.request.Request(
        f"{BASE}/{path}",
        data=json.dumps(body).encode() if body else None,
        headers={"x-goog-api-key": key, "Content-Type": "application/json"})
    try:
        with urllib.request.urlopen(req, timeout=20) as r:
            return r.status, json.load(r)
    except urllib.error.HTTPError as e:
        try:
            return e.code, json.load(e)
        except Exception:
            return e.code, {}
 
def classify(model, key):
    # 1) 名前だけ先に見る。生成しないので、枠を使わない
    status, _ = call(f"models/{model}", key)
    if status == 404:
        return "MODEL_NAME", "このキーから名前が見えない。綴り・世代・利用者限定を疑う"
    if status in (400, 403):
        return "KEY_OR_PROJECT", f"キーかプロジェクトの問題 ({status})"
    # 2) 名前が通ったときだけ、出力1トークンの生成で上限を見る
    status, body = call(
        f"models/{model}:generateContent", key,
        {"contents": [{"parts": [{"text": "ping"}]}],
         "generationConfig": {"maxOutputTokens": 1}})
    if status == 429:
        return "QUOTA", "本物の上限。待つか、枠の見直しへ"
    if status == 200:
        return "OK", "この名前は通る。アプリ側のリトライ・フォールバックを疑う"
    return "OTHER", f"HTTP {status}"
 
# 実行例: classify("モデル名", "YOUR_API_KEY")

YOUR_API_KEY はご自分のキーに置き換えてください。1トークンで切るのは、確認のための呼び出しが枠を食わないようにするためです。

キーを使わずに、分類の分岐だけ確かめました

ここまでの流れを、私は実キーではなく、応答を差し替えた模擬で確かめています。名前の綴りが違う場合、枠が尽きた場合、すべて通る場合、キーが拒否された場合の4通りを並べたところ、それぞれ MODEL_NAME、QUOTA、OK、KEY_OR_PROJECT に分かれました。

ただし、これは私の書いた分岐が意図どおりに動くことの確認にすぎません。実際の API が、皆さまのキーで何を返すかは、手元で一度打ってみていただくのがいちばん確実です。その結果が OK なら、アプリ側の再試行の組み方へ目を移します。

ログに「依頼した名前」と「返ってきたコード」を1行で残します

対応表を作るには、リクエストごとに1行のログが要ります。難しいことはなく、次の程度で足ります。

import time
 
def log_attempt(op_id, model, status):
    # 1操作(op_id)が何回・どのモデルで・何を返されたかを後から並べられる
    print(f"{time.strftime('%H:%M:%S')} op={op_id} model={model} status={status}")

op_id を操作ごとに一つ振っておくと、1回の操作が3リクエストに増えていたことも、404 の次に 429 が来た順番も、そのまま読み取れます。ログを増やす前は「404 と 429 が出ている」としか言えませんでしたが、この1行があれば「本命は 404、落とし先が 429」と言い切れます。

直らないときの次の一手

OK が返るのにアプリでは失敗するなら、疑う場所は呼び出しの回数です。失敗時に別モデルへ落とす処理を一時的に切って、1操作が何リクエストになっているかを数えてください。名前が見えない場合は、2.5 Flash の 404 の例のように、公式表に停止日がなくても使えなくなることがあります。モデル一覧が 200 で通るのに別の理由で止まる場合は、403 の切り分け順も合わせてご覧ください。

429 のなかでも、待っても通らない種類への対処は、有料記事のリトライ設計で実装まで書いております。

まずは、ご自分のアプリのログから、404 を返したモデル名を1つだけ抜き出して、上のスクリプトに渡してみていただければ幸いです。名前が先、上限はそのあと。 この順番だけは、次に詰まったときも崩さないようにしています。

シェア

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

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

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

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

関連記事

◈ API / SDK2026-10-16
models は 200 なのに generateContent だけ 403 になる日 — 切り分けの順番を先に決めておく
モデル一覧の取得は 200 で通るのに、生成リクエストだけが 403 permission_denied で止まるときの切り分け手順です。キー・プロジェクト・請求の順に確かめる小さな診断スクリプトと、リトライしてはいけない理由、サポートへ渡す材料の揃え方をまとめました。
◈ API / SDK2026-05-17
Gemini API で画像バッチ分析の INVALID_ARGUMENT エラーを診断する
Gemini API で複数画像を一括分析するとき INVALID_ARGUMENT エラーが出て詰まった経験はありませんか。MIMEタイプ・サイズ制限・リクエスト構造という3つの原因を診断し、File API と inline data を使い分けて根本解決する実践ガイドです。
◈ API / SDK2026-09-04
ループ音源のプチノイズは、Gemini に聴かせる前に波形の端で切り分けられます
環境音のループ再生で折り返しだけがプチッと鳴る。音声理解に丸ごと投げる前に、波形の端の段差を内部の変化量で正規化してふるい分ける手順と、配布形式への変換で継ぎ目が作り直される落とし穴をまとめました。