Nano Banana 2で発生する429 RESOURCE_EXHAUSTEDや502 Bad Gatewayなどのエラーは、Gemini 3.1 Flash Image API(gemini-3.1-flash-image-preview)に影響を及ぼします。429エラーは全障害の約70%を占め、レート制限を超過したことを意味します。RPMリセットには60秒待つか、日次クォータ(太平洋時間の深夜にリセット)を確認してください。502エラーはGoogleサーバーの不正なレスポンスを示し、通常5〜15分で解消されます。本ガイドでは、検証済みのレート制限データ、実際のエラーレスポンス例、本番環境対応のPython・TypeScriptコードを使って、Nano Banana 2のすべてのエラーコードを網羅的に解説します。
Nano Banana 2のエラーがNano Banana Proと異なる理由
Nano Bananaのエラーをデバッグしていて、Nano Banana Pro向けに書かれたガイドに従っている場合、間違った解決策を適用している可能性があります。Nano Banana 2(モデルID: gemini-3.1-flash-image-preview)とNano Banana Pro(モデルID: gemini-3-pro-image-preview)は根本的に異なるモデルであり、料金体系、レート制限、エラーの挙動がそれぞれ異なります。これらの違いを理解することが、エラーを正しく修正し、無駄なデバッグ時間を避けるための第一歩です。
最も重要な違いは料金です。Nano Banana 2は入力100万トークンあたり$0.25、画像生成の出力100万トークンあたり$60であるのに対し、Nano Banana Proは入力100万トークンあたり$2.00、出力100万トークンあたり$120です(ai.google.dev/pricing、2026年3月2日確認)。つまり、NB2はトークン単価でProより50〜87%安く、1K解像度の画像1枚あたりの費用はNB2が約$0.067に対してProは$0.134です。この料金差はエラー処理において重要です。使用するモデルによってリトライ戦略のコストへの影響が異なるためです。Nano Banana 2とProの技術的な違いの詳細については、Nano Banana 2 vs Pro完全比較の専用記事をご覧ください。
2つ目の重要な違いは、Nano Banana 2が「プレビュー」モデルに分類されている点です。これは、確立されたモデルよりも厳しいレート制限の下で動作することを意味します。Googleの公式ドキュメントには「実験的モデルとプレビューモデルはレート制限が低い」と明記されています(ai.google.dev/docs/rate-limits、2026年3月2日確認)。実際には、Tier 1アカウントでNB2の画像生成は10 RPM程度に制限される場合があり、プレビューでないモデルよりも制限が厳しくなっています。NB2もProも画像生成の無料枠はありません。無料枠のアカウントでRESOURCE_EXHAUSTEDが表示される場合、それは課金を有効にしないと画像生成を利用できないことを示しています。
多くの開発者が見落としがちな技術的詳細として、マルチターン会話におけるthought_signatureの要件があります。Nano Banana 2を複数ターンにわたってテキストと画像の両方を生成する会話コンテキストで使用する場合、前回のレスポンスに含まれるthought_signatureを次のリクエストに含める必要があります。これを怠ると、この要件を知らない場合は紛らわしい400 Bad Requestエラーが発生します。この動作はNB2とProの両方で同じですが、NB2のほうが新しいため、この点を適切に説明しているチュートリアルが少ないのが現状です。
Nano Banana 2エラーを30秒で診断する方法

詳細な解決策に入る前に、このクイックリファレンステーブルを使って、発生しているエラーを正確に特定し、適切な修正方法にたどり着きましょう。Nano Banana 2のすべてのエラーは、自動リトライを実装すべきリトライ可能なエラーと、リクエストの内容を修正してから再試行する必要があるリトライ不可能なエラーの2つのカテゴリに分類されます。どちらのカテゴリに属するかを特定することで、間違ったアプローチに時間を浪費せずに済みます。
| HTTPコード | エラータイプ | 原因 | リトライ可能? | 復旧時間 |
|---|---|---|---|---|
| 429 | RESOURCE_EXHAUSTED | レート制限超過(RPM/RPD/TPM/IPM) | はい | 60秒(RPM)または太平洋時間深夜(RPD) |
| 502 | Bad Gateway | Googleの上流サーバー障害 | はい | 5〜15分 |
| 503 | Service Unavailable | サーバー過負荷(ピーク時) | はい | 30〜60分 |
| 500 | Internal Server Error | 予期しないサーバー障害 | はい | 状況による |
| 400 | Bad Request | 無効なパラメータまたはthought_signatureの欠落 | いいえ | リクエストペイロードを修正 |
| 403 | Forbidden | 無効なAPIキーまたはリージョン制限 | いいえ | 認証情報を修正 |
| 200 | IMAGE_SAFETY | セーフティシステムによるコンテンツフィルタリング | いいえ | プロンプトを言い換える |
最も重要なポイントは、失敗したリクエスト(429、502、503を返すもの)はGoogleから課金されないということです。課金されるのは画像生成が成功した場合のみです。つまり、リトライロジックを実装しても追加コストのリスクはゼロであり、エラー発生時に予算が膨れ上がることを心配している開発者にとって大きな安心材料です。アプリケーションがリトライ中に429エラーが連続しても、請求額はリトライがなかった場合と全く同じです。すべてのNano Bananaモデルにおけるエラー処理の概要については、Nano Bananaエラー完全トラブルシューティングガイドをご参照ください。
429エラー RESOURCE_EXHAUSTEDの修正方法 — Nano Banana 2で最も多いエラー
429 RESOURCE_EXHAUSTEDエラーは、Nano Banana 2を使用する際に最も頻繁に遭遇するエラーであり、すべてのAPI障害の推定70%を占めます。このエラーは、Googleが画像生成リクエストに対して適用する4つのレート制限ディメンションのいずれかに達したことを意味します。どの制限に達したかを正確に把握することが重要です。なぜなら、それぞれ異なる復旧戦略と待機時間があるからです。
429エラーを受信すると、APIは次のようなJSONレスポンスを返します。
json{ "error": { "code": 429, "message": "Resource has been exhausted (e.g. check quota).", "status": "RESOURCE_EXHAUSTED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "RATE_LIMIT_EXCEEDED", "metadata": { "consumer": "projects/YOUR_PROJECT_ID", "quota_limit": "GenerateContentRequestsPerMinutePerProjectPerModel", "quota_limit_value": "10" } } ] } }
エラーレスポンスのmetadataフィールドは、最も重要なデバッグツールです。quota_limitフィールドは、どの制限を超過したかを正確に教えてくれます。Nano Banana 2の画像生成における4つのレート制限ディメンションは、RPM(1分あたりのリクエスト数)、TPM(1分あたりのトークン数)、RPD(1日あたりのリクエスト数)、IPM(1分あたりの画像数)です。各ディメンションは独立して動作するため、1つに達しても他のディメンションには影響しません。Tier 1アカウントでは10 RPMでも1,000 RPDの場合があり、日次の割り当てを使い切ると、残りのRPMに関係なく、太平洋時間の深夜にRPDカウンターがリセットされるまで待つ必要があります。
RPM関連の429エラーの最も速い解決方法は、単純に60秒待つことです。RPMカウンターはローリング1分間ウィンドウでリセットされるため、60秒間リクエストを送信しなければ、RPMクォータの全容量が再び利用可能になります。ただし、RPD制限の場合は待機時間がはるかに長くなります。カウンターは太平洋時間の深夜(UTC-8、夏時間中はUTC-7)にリセットされます。太平洋時間の午前9時にRPD制限に達した場合、ティアをアップグレードしない限り15時間待つことになります。
よくある間違いは、できるだけ速くリクエストを送信し、リトライロジックで429エラーを処理しようとすることです。失敗したリクエストは課金されないため技術的には機能しますが、非効率であり、Googleのサーバーに不要な負荷をかけます。より良いアプローチは、自分側でプロアクティブなレート制限を実装することです。Tier 1の制限が10 RPMであることがわかっている場合、リクエストを少なくとも6秒間隔で送信すれば、制限内に安全に収まります。これにより、ほとんどの429エラーを発生前に防止できます。Nano Banana Pro 429エラーのトラブルシューティングでも同様の原則が適用されますが、レート制限の数値が異なります。
指数バックオフの実装は、残りの429エラーに対する標準的な解決策です。最初の失敗後は1秒の遅延から始め、リトライのたびに倍増させ(2秒、4秒、8秒、16秒)、複数のクライアントが同時にリトライする「サンダーリングハード」問題を防ぐために小さなランダムジッターを追加します。RPM関連の制限では最大リトライ遅延を60秒にキャップし、制限がRPMベースではなくRPDベースであると判断される場合は、5〜6回のリトライ後に断念することを検討してください。
502 Bad Gatewayと503 Service Unavailableエラーの修正方法
502 Bad Gatewayエラーと503 Service Unavailableエラーは、リクエストの問題ではなく、Googleのインフラストラクチャ側の問題を示すサーバーサイドエラーです。これらのエラーは429とは根本的に異なります。コードやレート制限の使用に問題はなく、Googleのサーバーが無効なレスポンスを返している(502)か、リクエストを処理できないほど過負荷になっている(503)のです。両方に対する正しい対処法は、忍耐と体系的なリトライロジックです。
502 Bad Gatewayが発生した場合、レスポンスは通常次のようになります。
json{ "error": { "code": 502, "message": "Bad Gateway", "status": "UNAVAILABLE" } }
502エラーは、Gemini APIの前に配置されたリバースプロキシまたはロードバランサーが、リクエストを処理する上流サーバーから無効なレスポンスを受信したことを意味します。これは、サーバーのデプロイメント、インフラストラクチャの更新、またはGoogleのデータセンター内の一時的なネットワーク問題の際に発生する可能性があります。重要なポイントは、502エラーはほぼ常に一時的なものであり、通常は何も操作しなくても5〜15分で解消されるということです。30分以上持続する502エラーが発生している場合は、Google Cloud Status DashboardでGemini APIに影響するサービスインシデントがないか確認してください。
503 Service Unavailableエラーは異なるパターンを示します。502エラーが通常は短時間の一時的な障害であるのに対し、503エラーは持続的なサーバー過負荷を示すことが多く、ピーク使用時間帯に多く発生します。コミュニティの報告と独自のテストに基づくと、Nano Banana 2のピークエラー率は平日のUTC 10:00〜14:00に集中する傾向があります。これは米国の朝と欧州の午後の作業時間が重なるタイミングです。アプリケーションが時間に敏感でない場合、オフピーク時間帯(UTC早朝や週末)に画像生成リクエストをスケジュールすることで、503エラー率を大幅に削減できます。
503レスポンスボディは502と似ていますが、通常はサーバーキャパシティに関するより具体的な情報が含まれます。
json{ "error": { "code": 503, "message": "The model is overloaded. Please try again later.", "status": "UNAVAILABLE" } }
Cherry Studio、Claude Code、DifyなどのツールでMCP(Model Context Protocol)経由でNano Banana 2にアクセスしているユーザーの場合、MCPレイヤーが独自のエラーラッピングを追加するため、サーバーサイドエラーが紛らわしい形で表示されることがあります。MCPクライアントで「upstream connection error」や「model not responding」のようなエラーが表示される場合、根本原因はGemini APIからの502または503である可能性が高いです。修正方法は同じで、待ってリトライすることです。特にCherry Studioユーザーは、サーバーログ(通常は~/.cherry-studio/logs/にあります)でAPIからの実際のHTTPステータスコードを確認し、MCPレイヤーの問題と実際のAPI障害を区別することをお勧めします。
502と503の両方のエラーは、429エラーよりも長い初期遅延を使用するリトライ戦略で処理する必要があります。最初のリトライでは5秒の遅延から始め、15秒、30秒と増加させ、60秒でキャップします。これらのエラーはサーバーサイドのストレスを示しているため、積極的なリトライは状況を悪化させる可能性があります。数分後に再試行するよう提案するユーザーフレンドリーなエラーメッセージとともに、最大3〜4回のリトライ後にグレースフルに失敗させてください。
クライアントエラーの修正 — 400 Bad Request、403 Forbidden、IMAGE_SAFETY
クライアントエラーは、上記のサーバーサイドエラーとは根本的に異なります。リトライしても修正されないリクエストの問題を示しているためです。同じ不正なリクエストを100回送信しても、100回同じエラーが返されます。再試行する前に、リクエストペイロード、認証情報、またはプロンプトの問題を特定して修正する必要があります。
400 Bad Requestは、複数の障害モードをカバーするため、最も多様なクライアントエラーです。Nano Banana 2に特有の最も一般的な原因は、マルチターン会話におけるthought_signatureの欠落です。NB2がシンキングトークンを含むレスポンスを返す場合(シンキングの可視性を「オフ」に設定してもシンキングトークンは常に課金されます)、レスポンスには同じ会話内の次のリクエストで渡す必要があるthought_signatureフィールドが含まれます。シグネチャが欠落している場合のエラーは次のようになります。
json{ "error": { "code": 400, "message": "Request contains an invalid argument: thought_signature is required for multi-turn conversations with this model.", "status": "INVALID_ARGUMENT" } }
修正方法は簡単ですが見落としやすいです。モデルのレスポンスからthought_signatureを抽出し、次のリクエストのgeneration_configに含めます。会話履歴を管理するフレームワークやSDKを使用している場合は、ターン間でこのフィールドが保持されることを確認してください。LangChainや一部のMCPサーバー実装を含む多くの人気フレームワークでは、これを自動的に処理しないため、シグネチャの抽出と注入にカスタムロジックの追加が必要になる場合があります。
その他の400エラーの原因として、無効なアスペクト比(NB2は1:1、3:4、4:3、9:16、16:9などの特定の比率をサポートしています。完全なリストは公式ドキュメントを確認してください)、サポートされていない画像サイズのリクエスト、参照画像の数の超過があります。Nano Banana 2は最大14枚の参照画像(10オブジェクトまたは6オブジェクト+5キャラクター)をサポートしており、この制限を超えると説明的なメッセージ付きの400エラーが発生します。
403 Forbiddenエラーは通常、3つのいずれかを意味します。APIキーが無効または取り消されている、Google CloudプロジェクトでGemini APIが有効になっていない、または地理的なリージョンがサービスへのアクセスを制限されている場合です。修正方法は具体的な原因によって異なります。まず、シンプルなテキストのみのリクエスト(課金不要)でAPIキーが正しいか確認します。テキストリクエストは機能するが画像生成が失敗する場合は、プロジェクトで課金を有効にする必要がある可能性が高いです。Nano Banana 2の画像生成には無料枠がないことを忘れないでください。
IMAGE_SAFETYブロックは特殊なカテゴリです。従来の意味でのHTTPエラーではなく、APIは200 OKステータスコードを返しますが、レスポンスボディは生成された画像がGoogleのセーフティフィルターによってブロックされたことを示します。レスポンスは次のようになります。
json{ "candidates": [ { "finishReason": "IMAGE_SAFETY", "safetyRatings": [ { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "probability": "HIGH", "blocked": true } ] } ] }
この場合、モデルは画像を生成しようとしましたが、配信前に出力がフラグ付けされました。セーフティブロックされた生成には課金されません。これを解決するには、セーフティフィルターをトリガーするコンテンツを避けるようにプロンプトを言い換えてください。「プロフェッショナルな写真」「エディトリアルスタイル」「クリーンなイラスト」などの明示的なスタイル指示を追加することで、フラグ付けされる可能性のあるコンテンツからモデルを遠ざけることができます。セーフティシステムは慎重な判断を行うため、複数の解釈が可能な曖昧な表現は避けてください。
Nano Banana 2のレート制限を完全解説 — すべてのティアと制限値

レート制限システムの全体像を理解することは、エラーが発生する前に予防するために不可欠です。Googleは、Nano Banana 2のレート制限を4つのディメンションと4つのティアにまたがって構造化しており、それぞれの組み合わせに、プロジェクトが送信できるリクエスト数を決定する具体的な数値制限が設定されています。これらのデータはすべて、2026年3月2日にai.google.dev/gemini-api/docs/rate-limitsから直接確認したものです。すべてのGeminiモデルの包括的な内訳については、Gemini APIレート制限のティア別完全ガイドをご覧ください。
4つのレート制限ディメンションは独立して動作します。RPM(1分あたりのリクエスト数)は、サイズに関係なくAPI呼び出しの数を制限します。TPM(1分あたりのトークン数)は、すべてのリクエストにわたる合計トークンスループットを制限します。RPD(1日あたりのリクエスト数)は、太平洋時間の深夜にリセットされる日次上限を設定します。IPM(1分あたりの画像数)は、画像生成出力を具体的に制限します。これらの制限のいずれかに達しても、他の制限には影響しません。たとえば、RPMの容量が残っていても、その分のIPMクォータを使い果たしている場合があります。
レート制限はAPIキーごとではなく、Google Cloudプロジェクトごとに適用されます。これは多くの開発者が見落とす重要な区別です。同じプロジェクトで複数のAPIキーを作成してレート制限を倍増させようとしても機能しません。単一プロジェクト下のすべてのキーは同じレート制限プールを共有します。実効的なレート制限を本当に増やすには、別のGoogle Cloudプロジェクトを作成する必要がありますが、このアプローチには課金管理に関する独自の複雑さがあり、特定のアーキテクチャ上の理由がない限り一般的には推奨されません。
Googleのティアシステムは、FreeからTier 1、Tier 2、Tier 3へと進行します。無料ティアはNano Banana 2の画像生成を一切サポートしていません。課金を有効にせずに画像を生成しようとすると、即座に429エラーが返されます。Tier 1は課金を有効にすると有効化され、基本的な画像生成の制限が提供されます。Tier 2は過去30日間の累計支出が$250以上、Tier 3は$1,000以上を必要とします。各ティアのアップグレードにより、4つすべてのディメンションで大幅に高い制限が適用されます。
Tier 1アカウントの実質的な意味は、1分あたり約10枚、1日あたり最大1,000枚の画像を生成できるということです。アプリケーションがリアルタイムでユーザーリクエストを処理する場合、持続的には約6秒に1つの画像リクエストを処理でき、または最大10件の同時リクエストの短いバーストの後に必須のクールダウン期間が続きます。画像をバッチ処理するアプリケーション(製品カタログやソーシャルメディアコンテンツの生成など)の場合、RPMではなくRPDの1日あたり1,000件の制限が制約となることが多いです。
Batch APIは大量ワークロード向けの代替手段を提供します。Nano Banana 2はバッチ処理をサポートしており、キュー制限はTier 1で100万トークン、Tier 2で2億5,000万トークン、Tier 3で7億5,000万トークンです。バッチリクエストは低い優先度で非同期に処理されますが、同期リクエストと同じRPM制限の対象にはなりません。リアルタイムの画像生成が必要ないユースケースでは、Batch APIはティアのアップグレードなしでスループットを劇的に向上させることができます。laozhang.aiのようなサービスは、レート制限が緩和されたNano Banana 2へのアクセスを1画像あたり約$0.05で提供しており、複数のGoogle Cloudプロジェクトの管理の複雑さやティアアップグレードの待ち時間なしに、より高いスループットを必要とする開発者にとって実用的な代替手段となります。
Nano Banana 2の本番環境対応エラーハンドリングコード

堅牢なエラーハンドリングを実装するには、API呼び出しをtry-catchブロックで囲むだけでは不十分です。本番環境対応のソリューションには、ジッター付き指数バックオフ、障害が発生しているサービスへの過剰な呼び出しを防ぐサーキットブレーカーパターン、レート制限内に収まるためのプロアクティブなリクエストキューイングを含める必要があります。以下は、Nano Banana 2統合に適用できるPythonとTypeScriptの完全な実装です。
Python実装
pythonimport time import random import google.generativeai as genai from collections import deque from threading import Lock class NanoBanana2Client: """Production error handler for Nano Banana 2 (gemini-3.1-flash-image-preview)""" MODEL_ID = "gemini-3.1-flash-image-preview" def __init__(self, api_key: str, max_rpm: int = 10): genai.configure(api_key=api_key) self.model = genai.GenerativeModel(self.MODEL_ID) self.max_rpm = max_rpm self.request_timestamps = deque() self.lock = Lock() self.circuit_open = False self.circuit_failures = 0 self.circuit_threshold = 5 self.circuit_reset_time = 0 def _wait_for_rate_limit(self): """Proactive rate limiting - prevent 429 before it happens""" with self.lock: now = time.time() # Remove timestamps older than 60 seconds while self.request_timestamps and self.request_timestamps[0] < now - 60: self.request_timestamps.popleft() if len(self.request_timestamps) >= self.max_rpm: wait_time = 60 - (now - self.request_timestamps[0]) + 0.1 if wait_time > 0: time.sleep(wait_time) self.request_timestamps.append(time.time()) def _check_circuit_breaker(self): """Circuit breaker - stop hammering a failing service""" if self.circuit_open: if time.time() > self.circuit_reset_time: self.circuit_open = False self.circuit_failures = 0 else: raise Exception( f"Circuit breaker open. Retry after " f"{int(self.circuit_reset_time - time.time())}s" ) def generate_image(self, prompt: str, max_retries: int = 5, **kwargs): """Generate image with full error handling""" self._check_circuit_breaker() self._wait_for_rate_limit() for attempt in range(max_retries): try: response = self.model.generate_content( prompt, generation_config=genai.types.GenerationConfig( response_mime_type="image/png", **kwargs ) ) # Check for IMAGE_SAFETY block if hasattr(response, 'candidates') and response.candidates: candidate = response.candidates[0] if hasattr(candidate, 'finish_reason'): if candidate.finish_reason.name == "IMAGE_SAFETY": return {"error": "IMAGE_SAFETY", "retryable": False, "message": "Content blocked by safety filter"} # Success - reset circuit breaker self.circuit_failures = 0 return {"success": True, "response": response} except Exception as e: error_code = getattr(e, 'code', None) or self._extract_code(str(e)) if error_code == 429: # Rate limit - exponential backoff with jitter delay = min(60, (2 ** attempt) + random.uniform(0, 1)) time.sleep(delay) continue elif error_code in (502, 503): # Server error - longer backoff self.circuit_failures += 1 if self.circuit_failures >= self.circuit_threshold: self.circuit_open = True self.circuit_reset_time = time.time() + 120 delay = min(60, 5 * (2 ** attempt) + random.uniform(0, 2)) time.sleep(delay) continue elif error_code in (400, 403): # Client error - do not retry return {"error": error_code, "retryable": False, "message": str(e)} else: # Unknown error return {"error": "UNKNOWN", "retryable": False, "message": str(e)} return {"error": "MAX_RETRIES", "retryable": True, "message": f"Failed after {max_retries} attempts"} def _extract_code(self, error_str: str) -> int: for code in [429, 502, 503, 500, 400, 403]: if str(code) in error_str: return code return 0
TypeScript / Node.js実装
typescriptimport { GoogleGenerativeAI } from "@google/generative-ai"; interface GenerationResult { success: boolean; response?: any; error?: string; retryable?: boolean; message?: string; } class NanoBanana2Client { private static MODEL_ID = "gemini-3.1-flash-image-preview"; private model: any; private requestTimestamps: number[] = []; private maxRpm: number; private circuitOpen = false; private circuitFailures = 0; private circuitThreshold = 5; private circuitResetTime = 0; constructor(apiKey: string, maxRpm = 10) { const genAI = new GoogleGenerativeAI(apiKey); this.model = genAI.getGenerativeModel({ model: NanoBanana2Client.MODEL_ID }); this.maxRpm = maxRpm; } private async waitForRateLimit(): Promise<void> { const now = Date.now(); this.requestTimestamps = this.requestTimestamps .filter(ts => ts > now - 60000); if (this.requestTimestamps.length >= this.maxRpm) { const waitMs = 60000 - (now - this.requestTimestamps[0]) + 100; if (waitMs > 0) await this.sleep(waitMs); } this.requestTimestamps.push(Date.now()); } async generateImage( prompt: string, maxRetries = 5 ): Promise<GenerationResult> { if (this.circuitOpen) { if (Date.now() > this.circuitResetTime) { this.circuitOpen = false; this.circuitFailures = 0; } else { const waitSec = Math.ceil( (this.circuitResetTime - Date.now()) / 1000 ); return { success: false, error: "CIRCUIT_OPEN", retryable: true, message: `Circuit breaker open. Retry in ${waitSec}s` }; } } await this.waitForRateLimit(); for (let attempt = 0; attempt < maxRetries; attempt++) { try { const result = await this.model.generateContent({ contents: [{ role: "user", parts: [{ text: prompt }] }], generationConfig: { responseMimeType: "image/png" }, }); const candidate = result.response?.candidates?.[0]; if (candidate?.finishReason === "IMAGE_SAFETY") { return { success: false, error: "IMAGE_SAFETY", retryable: false, message: "Content blocked by safety filter" }; } this.circuitFailures = 0; return { success: true, response: result.response }; } catch (err: any) { const code = err?.status || err?.code || this.extractCode(err.message); if (code === 429) { const delay = Math.min(60000, (2 ** attempt) * 1000 + Math.random() * 1000); await this.sleep(delay); continue; } if (code === 502 || code === 503) { this.circuitFailures++; if (this.circuitFailures >= this.circuitThreshold) { this.circuitOpen = true; this.circuitResetTime = Date.now() + 120000; } const delay = Math.min(60000, 5000 * (2 ** attempt) + Math.random() * 2000); await this.sleep(delay); continue; } if (code === 400 || code === 403) { return { success: false, error: String(code), retryable: false, message: err.message }; } return { success: false, error: "UNKNOWN", retryable: false, message: err.message }; } } return { success: false, error: "MAX_RETRIES", retryable: true, message: `Failed after ${maxRetries} attempts` }; } private sleep(ms: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } private extractCode(msg: string): number { for (const code of [429, 502, 503, 500, 400, 403]) { if (msg?.includes(String(code))) return code; } return 0; } }
両方の実装は、本番環境に対応するための3つの重要なアーキテクチャパターンを共有しています。第一に、プロアクティブなレート制限がリクエストのタイムスタンプを追跡し、Googleのレート制限に達する前に新しいリクエストを遅延させることで、ほとんどの429エラーの発生を未然に防ぎます。第二に、サーキットブレーカーパターンがサーバーの劣化状態(5回連続の失敗後)を検出し、2分間一時的にリクエストの送信を停止することで、過負荷を悪化させるのではなくサーバーに回復の時間を与えます。第三に、ジッター付き指数バックオフ戦略がリトライ間に段階的に長い遅延を使用し、ランダム性を加えることで、複数のクライアントが同時にリトライする問題を防止します。
エラーが続く場合の対処法 — 代替手段とコスト最適化
上記のすべてのエラーハンドリング戦略を実装しても定期的にレート制限に達する場合、問題は技術的ではなくアーキテクチャ的なものである可能性が高いです。現在のティアのキャパシティを超えているため、3つの実用的な方法があります。Google Cloudのティアをアップグレードする、リクエストパターンを最適化する、またはより高い制限を提供するAPIプロキシサービスを使用するかです。
ティアのアップグレードは最も簡単な解決策ですが、Googleの支出しきい値を満たす必要があります。Tier 1からTier 2への移行には30日間で$250の累計API支出が必要で、RPMは10から30に3倍、RPDは1,000から5,000に5倍になります。多くの本番アプリケーションでは、Tier 2の制限で十分です。Tier 3(30日間で$1,000以上の支出)ではすべてが再び倍増し、60 RPMと10,000 RPDになり、かなりのワークロードを処理できます。支出しきい値を満たすと自動的に移行され、申請プロセスや手動承認は不要です。
リクエストパターンの最適化により、ティアアップグレードの必要性を遅延させたり排除できることがよくあります。画像生成ジョブをバッチ処理し、RPM制限のすぐ下の安定したレートで処理するリクエストキューの実装を検討してください。生成された画像をキャッシュして、同じプロンプトで同じ画像を二度と生成しないようにします。時間に敏感でないワークロードにはBatch APIを使用してください。標準のRPM制限の外で動作します。また、複数の解像度で画像を生成する場合は、プレビュー用に512px(1画像あたり$0.045)から始め、確定した選択のみ高解像度を生成してください。
APIプロキシサービスは、より高いレート制限とコスト削減を組み合わせた第3の方法を提供します。laozhang.aiのようなサービスは、レート制限の制約なしに1画像あたり約$0.05でNano Banana 2へのアクセスを提供しています。これは、Googleの直接価格(1K解像度で$0.067)と比較して競争力があり、より高い解像度よりも大幅に安価です。最安値のNano Banana 2 API代替サービスでは、主要なプロバイダーをすべて比較した専用記事をご用意しています。トレードオフとして、プロキシサービスはネットワークホップとサードパーティプロバイダーへの依存が追加されるため、非クリティカルなワークロードや、プライマリのGoogle Cloudクォータが枯渇した際のフォールバックとして最適です。
以下は、1K解像度で1日あたり1,000枚の画像を生成する場合の実用的なコスト比較です。
| プロバイダー | 1画像あたりのコスト | 日次コスト(1,000画像) | レート制限 | 最適な用途 |
|---|---|---|---|---|
| Google Direct(Tier 1) | $0.067 | $67.00 | 10 RPM / 1,000 RPD | 開発、少量利用 |
| Google Direct(Tier 2) | $0.067 | $67.00 | 30 RPM / 5,000 RPD | 本番環境、中量利用 |
| Google Direct(Tier 3) | $0.067 | $67.00 | 60 RPM / 10,000 RPD | エンタープライズ、大量利用 |
| laozhang.ai | 約$0.05 | 約$50.00 | 厳格なRPM制限なし | コスト重視、大量利用 |
Googleの料金はすべてのティアで同一です。ティアはレート制限にのみ影響し、1画像あたりのコストには影響しません。つまり、ティアアップグレードの価値は純粋にスループットキャパシティに関するものであり、単位経済性ではありません。コストが主な懸念事項で、プロキシサービスを利用しても問題ない場合は、1画像あたり約25%の節約と事実上無制限のレート制限を得ることができます。ドキュメントはdocs.laozhang.aiで利用可能で、画像生成のテストはimages.laozhang.aiで行えます。
よくある質問
Nano Banana 2の429エラーを修正するにはどうすればよいですか?
429 RESOURCE_EXHAUSTEDエラーは、RPM(1分あたりのリクエスト数)、TPM(1分あたりのトークン数)、RPD(1日あたりのリクエスト数)、IPM(1分あたりの画像数)の4つのレート制限のいずれかを超過したことを意味します。RPM制限の最も速い修正方法は60秒待つことです。RPD制限の場合は太平洋時間の深夜まで待つ必要があります。コードに指数バックオフを実装し、1秒の遅延から始めて、最大60秒まで各リトライで倍増させてください。リクエストを制限以下に収まるようにプロアクティブに間隔を空けてください。Tier 1アカウントの場合、画像生成は1分あたり10リクエスト以内です。
Nano Banana 2のレート制限は何ですか?
Nano Banana 2(gemini-3.1-flash-image-preview)のレート制限はティアによって異なります。Tier 1(課金有効)では画像生成に10 RPM、4M TPM、1,000 RPD、10 IPMが許可されます。Tier 2(30日間で$250以上の支出)では30 RPM、10M TPM、5,000 RPD、30 IPMが許可されます。Tier 3($1,000以上の支出)では60 RPM、20M TPM、10,000 RPD、60 IPMが許可されます。無料ティアは画像生成をサポートしていません。これらの制限はAPIキーごとではなくプロジェクトごとに適用され、2026年3月2日にai.google.devから確認しました。
Nano Banana 2で502エラーが繰り返し発生するのはなぜですか?
502 Bad Gatewayエラーは、あなたのコードではなくGoogleのサーバー側の問題を示しています。これらのエラーは通常5〜15分で解消されます。ピーク使用時間帯(UTC 10:00〜14:00)に最も発生しやすいです。5秒の初期遅延から始めて30〜60秒まで増加するリトライロジックを実装してください。30分以上502エラーが続く場合は、Google Cloud Status Dashboardでサービスインシデントを確認してください。失敗した502リクエストに対しては課金されません。
Nano Banana 2は無料で使えますか?
Nano Banana 2のテキストのみのリクエストは無料ティアで利用可能ですが、画像生成には課金の有効化(Tier 1以上)が必要です。NB2の画像生成に無料枠はありません。1画像あたりのコストは$0.045(512px)から$0.151(4K解像度)です。入力トークンは100万あたり$0.25、画像出力トークンは100万あたり$60で、2026年3月2日にGoogleの公式料金ページから確認しています。
Nano Banana 2のthought_signatureエラーとは何ですか?
thought_signatureエラー(400 Bad Request)は、マルチターン会話でモデルの前回のレスポンスに含まれるthought_signatureを含めなかった場合に発生します。シンキングの可視性を「オフ」に設定していても、NB2はシンキングトークンを生成し、後続のターンで返す必要があるシグネチャを含みます。APIレスポンスからthought_signatureフィールドを抽出し、次のリクエストのgeneration_configに含めることでこのエラーを解決できます。
Nano Banana 2とProではエラーにどのような違いがありますか?
Nano Banana 2とProは同じエラーコード(429、502、503、400、403、IMAGE_SAFETY)を共有しますが、レート制限と料金が異なります。NB2はトークン単価で50〜87%安いですが、プレビューモデルとしてより厳しいレート制限の下で動作します。NB2の入力コストは$0.25/100万トークンに対してProは$2.00/100万、NB2の出力コストは$60/100万に対してProは$120/100万です。両方とも画像生成の無料枠はありません。エラー耐性に関しては、Proは非プレビューステータスのため、同じティアレベルでわずかにより緩やかな制限を持つ場合があります。
