GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-05-05中級

Gemini API レート制限エラーを完全解決するトラブルシューティングガイド

Gemini API の 429 Too Many Requests・RESOURCE_EXHAUSTED エラーの原因と解決方法を解説。指数バックオフ実装から無料枠の上限管理まで、実際のコードで対策を紹介します。

Gemini API191レート制限4429エラーRESOURCE_EXHAUSTEDトラブルシューティング30

API 開発で最初に壁にぶつかるのが、レート制限エラーです。

Gemini API を使い始めてしばらく経つと、429 Too Many RequestsRESOURCE_EXHAUSTED といったエラーに遭遇することがあります。これらは「使いすぎ」のシグナルですが、ただ待てばいいというわけでもなく、適切な実装がないとエラーが繰り返し発生します。

ここではGemini API のレート制限の仕組みを理解した上で、実際のコードで対策する方法を整理しました。

Gemini API のレート制限の種類

Gemini API には、主に3種類のレート制限があります。

RPM(Requests Per Minute): 1分あたりのリクエスト数の上限 TPM(Tokens Per Minute): 1分あたりに処理できるトークン数の上限 RPD(Requests Per Day): 1日あたりのリクエスト数の上限

無料枠(Google AI Studio や Gemini API の無料ティア)では特にこれらの制限が厳しく、開発中にすぐ上限に到達することがあります。有料の API を使用している場合も、急激なトラフィック増加時にはレート制限に当たることがあります。

最新の制限値は Google の公式ドキュメントで確認してください。モデルや利用プランによって異なります。

基本的な解決策:指数バックオフの実装

レート制限エラーが発生したとき、最も重要な対策は「適切な待機とリトライ」です。単純に固定時間待機するのではなく、リトライのたびに待機時間を増やす「指数バックオフ」が標準的な実装パターンです。

import time
import random
import google.generativeai as genai
from google.api_core import exceptions
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-2.5-flash-preview-05-20")
 
def generate_with_retry(prompt: str, max_retries: int = 5) -> str:
    """
    指数バックオフでレート制限エラーを自動リトライする関数
    """
    for attempt in range(max_retries):
        try:
            response = model.generate_content(prompt)
            return response.text
            
        except exceptions.ResourceExhausted as e:
            if attempt == max_retries - 1:
                # 最終リトライでも失敗した場合は例外を再送出
                raise
            
            # 指数バックオフ: 2^attempt 秒 + ランダムジッター
            wait_time = (2 ** attempt) + random.uniform(0, 1)
            print(f"レート制限エラー。{wait_time:.1f}秒後にリトライ... (試行 {attempt + 1}/{max_retries})")
            time.sleep(wait_time)
            
        except Exception as e:
            # レート制限以外のエラーはリトライしない
            raise
 
# 使用例
try:
    result = generate_with_retry("Pythonの非同期処理について説明してください")
    print(result)
except exceptions.ResourceExhausted:
    print("最大リトライ回数に達しました。しばらく待ってから再実行してください。")

random.uniform(0, 1) のジッター(ゆらぎ)を加えているのは、複数のクライアントが同時にリトライするときに「全員が同じタイミングでリクエストを送る」状況(雷鳴群れ問題)を防ぐためです。

バッチ処理でのレート制限対策

複数のリクエストを一度に処理するバッチ処理では、事前にリクエスト間隔を制御する点が肝心です。

import time
import asyncio
import google.generativeai as genai
from google.api_core import exceptions
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-2.5-flash-preview-05-20")
 
async def process_batch(prompts: list[str], rpm_limit: int = 10) -> list[str]:
    """
    RPM制限を考慮してバッチ処理を行う非同期関数
    rpm_limit: 1分あたりの最大リクエスト数
    """
    results = []
    delay = 60.0 / rpm_limit  # リクエスト間の最小待機時間(秒)
    
    for i, prompt in enumerate(prompts):
        try:
            response = model.generate_content(prompt)
            results.append(response.text)
            
            # 最後のリクエスト以外は待機
            if i < len(prompts) - 1:
                await asyncio.sleep(delay)
                
        except exceptions.ResourceExhausted:
            # エラーが発生した場合は追加で30秒待機してリトライ
            print(f"レート制限。30秒待機してリトライします...")
            await asyncio.sleep(30)
            
            try:
                response = model.generate_content(prompt)
                results.append(response.text)
            except Exception as e:
                results.append(f"エラー: {str(e)}")
    
    return results
 
# 使用例
async def main():
    prompts = [
        "Pythonのリスト内包表記を説明してください",
        "辞書の使い方を教えてください",
        "クラスの基本的な書き方を示してください",
    ]
    
    results = await process_batch(prompts, rpm_limit=10)
    for i, result in enumerate(results):
        print(f"--- 結果 {i+1} ---")
        print(result[:200])
 
asyncio.run(main())

よくある間違いと正しい対処法

間違い1: エラーをキャッチせずにループを続ける

# ❌ レート制限エラーでループが止まる
for prompt in large_list:
    response = model.generate_content(prompt)  # エラーで全体が停止
    results.append(response.text)
# ✅ エラーをキャッチして適切に処理する
for prompt in large_list:
    try:
        response = model.generate_content(prompt)
        results.append(response.text)
    except exceptions.ResourceExhausted:
        time.sleep(60)  # 1分待機してリトライ
        response = model.generate_content(prompt)
        results.append(response.text)

間違い2: 大きなプロンプトを分割せずに送る

トークン数の多いリクエストは TPM 制限に当たりやすくなります。長い文書を一度に処理しようとするより、チャンクに分割して複数のリクエストに分けることで、TPM の消費を分散できます。

間違い3: エラーメッセージを確認しない

ResourceExhausted エラーにはエラーメッセージが含まれており、どの制限(RPM か TPM か RPD か)に当たっているかが分かる場合があります。エラーメッセージを確認することで、適切な対策が取りやすくなります。

無料枠での開発を効率化するコツ

開発初期に無料枠を使っている場合は、以下の工夫でレート制限エラーを減らせます。

リクエストをキャッシュします。同じプロンプトに対して毎回 API を叩くのではなく、初回のレスポンスを保存しておいて再利用します。特に開発中のテストや反復作業で効果があります。

短いプロンプトで動作確認します。本番用の長いプロンプトの開発中は、まず短い要約プロンプトで動作確認し、完成したら本番プロンプトで検証します。

開発と本番で API キーを分ける。本番の APIキーに開発のリクエストが混ざると、制限管理が難しくなります。

Gemini API の活用全般については、Google AI Studio と OpenAI Playground の比較記事も参考になります。

送信前にトークン数を数えて TPM 超過を防ぐ

レート制限のうち TPM(1分あたりのトークン数)は、リクエストの本数が少なくても引っかかります。長い文書を1回で送ると、それだけで上限に届いてしまうことがあるためです。

送信前にトークン数を数えておくと、TPM 超過を未然に避けられます。count_tokens は API を呼びますが、生成の課金は発生しません。検証用に気軽に使える点がありがたいところです。

def count_tokens_before_send(model_name: str, contents: list) -> int:
    """送信前にトークン数を数えて確認します(生成課金は発生しません)"""
    model = genai.GenerativeModel(model_name)
    token_count = model.count_tokens(contents)
    total = token_count.total_tokens
 
    # 警告閾値(例:50万トークン)
    if total > 500_000:
        print(f"⚠️ 大きなリクエスト: {total:,}トークン")
        print("  処理に時間がかかる可能性があります")
 
    return total
 
token_count = count_tokens_before_send(
    "gemini-2.5-pro-latest",
    ["非常に長い文書の内容..."]
)
print(f"トークン数: {token_count:,}")

同じプロンプトでも入力トークンが10万から50万に増えると、レイテンシが2〜3倍に伸びることがあります。「入れられること」と「入れるべきこと」は別なのだと、計測しながら実感しました。

エラーコード別に「待つべきか、直すべきか」を見分ける

Gemini API が返すエラーを、すべて同じように扱ってはいけません。リトライで解決するエラーと、コードを直さないと永遠に直らないエラーがあるためです。形式の間違ったリクエストをリトライしても、クォータを無駄に消費するだけになります。

リトライすべきエラーは、サーバー側や混雑が原因の一過性のものです。

  • 429 RESOURCE_EXHAUSTED:レート制限。指数バックオフでリトライします
  • 500 INTERNAL_SERVER_ERROR:一時的なサーバー問題。少し待ってリトライします
  • 503 SERVICE_UNAVAILABLE:サービス一時停止。数分待ってリトライします

リトライしてはいけないのは、リクエスト側に原因があるエラーです。

  • 400 INVALID_ARGUMENT:リクエストの形式が間違っています。コードを修正します
  • 403 PERMISSION_DENIED:API キーの権限が不足しています
  • 404 NOT_FOUND:モデル名が間違っています
  • StopCandidateException(安全フィルター):プロンプト自体を見直す必要があります
def classify_error(error: Exception) -> str:
    """エラーの種類を分類します"""
    error_str = str(error).lower()
 
    if "429" in error_str or "resource_exhausted" in error_str:
        return "rate_limit"       # リトライ可
    elif "500" in error_str or "503" in error_str:
        return "server_error"     # リトライ可
    elif "400" in error_str:
        return "invalid_request"  # コード修正が必要
    elif "403" in error_str:
        return "auth_error"       # API キーを確認
    else:
        return "unknown"

最初にこの分類を1か所にまとめておくと、リトライ処理の見通しがよくなります。

使用量をモニタリングしてコストを把握する

レート制限への対処と並んで、本番で効いてくるのが使用量の可視化です。どれだけ呼び、どれだけトークンを使ったかが見えていないと、コストもエラーの傾向もつかめません。

import time
from dataclasses import dataclass, field
 
@dataclass
class UsageStats:
    """API の使用量を追跡するシンプルなクラスです"""
    requests: int = 0
    input_tokens: int = 0
    output_tokens: int = 0
    errors: int = 0
    start_time: float = field(default_factory=time.time)
 
    def add_response(self, response: genai.types.GenerateContentResponse):
        self.requests += 1
        if hasattr(response, "usage_metadata"):
            self.input_tokens += response.usage_metadata.prompt_token_count
            self.output_tokens += response.usage_metadata.candidates_token_count
 
    def print_summary(self):
        elapsed = time.time() - self.start_time
        # Gemini 2.5 Pro の料金(2026年4月時点・最新値は公式で確認してください)
        # 入力: $1.25/1M tokens(200K以下)、出力: $10/1M tokens
        input_cost = (self.input_tokens / 1_000_000) * 1.25
        output_cost = (self.output_tokens / 1_000_000) * 10.0
 
        print(f"=== 使用量サマリー ===")
        print(f"経過時間: {elapsed:.1f}秒")
        print(f"リクエスト数: {self.requests}件(エラー: {self.errors}件)")
        print(f"入力トークン: {self.input_tokens:,}")
        print(f"出力トークン: {self.output_tokens:,}")
        print(f"推定コスト: ${input_cost + output_cost:.4f}")
 
stats = UsageStats()
response = generate_with_retry("質問内容")
stats.add_response(response) if response else None
stats.print_summary()

料金は改定されることがあるため、係数は公式の料金ページで確認してから使ってください。

本番環境で見落としがちな設定 — タイムアウトとフォールバック

レート制限の実装が整っても、本番ではもう一歩の備えが要ります。

タイムアウトを明示します。既定では長時間かかるリクエストがタイムアウトしないため、本番ではハングしたリクエストがリソースを占有し続けます。

response = model.generate_content(
    contents,
    request_options={"timeout": 120}  # 120秒でタイムアウト
)

モデルのフォールバックを用意します。混雑時に Gemini 2.5 Pro が詰まっても、一部のタスクは Flash で十分な品質を保てます。重要度でモデルを振り分けておくと、コストと Pro 側のレート制限への露出を同時に下げられます。

最初はとにかくログを残します。どのエラーが何回起きているかが見えれば、対処の優先順位は自然に決まっていきます。本番のエラー分布は事前の予想とずれることが多く、見えないものは直しようがありません。

レート制限は「壊れている」サインではありません

レート制限エラーは、Gemini API が壊れているサインではありません。適切なリトライ実装とリクエスト間隔の管理さえあれば、本番環境でも安定して動くシステムが作れます。まず自分のアプリケーションの RPM/TPM の使用量を把握し、制限に余裕を持たせた設計にしておくことが、長く安定して動かす近道です。

私自身、個人開発で Dolice Labs の複数ブログの記事生成や、手元のアプリのバックエンドを Gemini で回しています。最初の頃はバッチをそのまま流して 429 に何度もぶつかり、そのたびに手が止まりました。間隔を空けてリトライを挟むだけで、同じ処理が静かに通るようになった瞬間に、レート制限は敵ではなく前提なのだと腑に落ちました。

エラーログを丁寧に取りながら、自分のトラフィックで何が起きるかを少しずつ確かめていく。その積み重ねが、結局いちばん堅い対策になります。この記事が参考になれば幸いです。

シェア

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

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

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

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

関連記事

API / SDK2026-06-22
Gemini API × Google Cloud 本番エラーを層で切り分ける診断手順
Gemini APIをGoogle Cloud本番環境で運用する際のエラーを体系的に診断。IAM権限・Vertex AI vs AI Studio・VPC・クォータ管理・サービスアカウント設定まで、実装コード付きで完全解説します。
API / SDK2026-06-21
Gemini API モデル非推奨・移行エラーの対処法
Gemini API でモデルが非推奨になった時の移行手順と、移行時に発生するエラーの対処法を詳しく解説します。
API / SDK2026-06-03
Gemini Live API の応答音声が速回しに聞こえる — サンプルレート取り違えの直し方
Gemini Live API の応答音声が甲高く速回しに聞こえる、あるいはノイズ混じりになる症状は、ほとんどが 24kHz の出力を別のサンプルレートで再生していることが原因です。ブラウザと iOS の両方で、取り違えを直す具体的なコードを記録します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →