概要
gemini-3-pro-image(つまり、Nano Banana Pro)は厳格なコンテンツ安全性制御を適用しており、複数のレイヤーでポリシーに準拠しないリクエストを拒否します。「生成に失敗しました」という単純なメッセージでは、ユーザーは問題を理解できません。適切なエラーハンドリングでは、次のことが必要です。
- 拒否理由を正確に特定する — コンテンツ違反、ナレッジベースの制限、技術的エラーを区別します
- ユーザーにわかりやすく伝える — 技術的なエラーを理解しやすい説明に変えます
- 実行可能な提案をする — リクエストをどのように調整すれば成功するかをユーザーに伝えます
- 技術的な詳細をすべて保持する — 開発者によるデバッグのために必要です
リクエストがHTTP 200を返すものの画像がない場合、通常はGoogle側の安全性判断によるものです。APIYIの透過プロキシは結果をそのまま転送するだけです。私たちもお客様に画像生成を成功させていただきたいと考えています。検出とメッセージのロジックは、アプリケーション側で実装する必要があります。
Google コンテンツモデレーションポリシー(2026年更新)
Googleの画像生成は、二層の安全メカニズムを使用しています:- 設定可能なフィルター: ハラスメント、ヘイトスピーチ、露骨な性的コンテンツ、危険なコンテンツの4カテゴリを対象とし、
safetySettingsで調整可能です - 組み込みの保護: 児童の安全などの中核的な危害に対して常に有効で、パラメータで無効化することはできません
- 生成AI禁止使用ポリシー:
policies.google.com/terms/generative-ai/use-policy - 生成コンテンツの一般的なエラー参照:
ai.google.dev/api/generate-content
3つのコア診断指標
優先度の高い順に確認してください:1. candidatesTokenCount(最優先)⭐
- 位置:
response.usageMetadata.candidatesTokenCount - 意味: APIによって生成された候補コンテンツの token 数
- ルール:
0の値は、リクエストがコンテンツモデレーション段階で即座に拒否されたこと(候補コンテンツが一切生成されなかったこと)を意味します。これは最も厳格な拒否です。
candidatesTokenCount が 0 である場合、必ずしもポリシー違反を意味するわけではありません。以下の他の2つの一般的なケースを区別する必要があります:- レスポンスに
promptFeedback.blockReasonが存在し、candidatesがない場合: 生成前のプロバイダーによるチェックで入力がブロックされました。OTHERは多くの場合、1枚の参照画像によってトリガーされます。blockReason: OTHER のトラブルシューティング を参照してください finishReasonがNO_IMAGEの場合: 通常、prompt がモデルに提案や分析の記述を求めているため、画像の意図が不明確になっています。NO_IMAGE トラブルシューティング を参照してください
2. finishReason(第2優先)
- 位置:
response.candidates[0].finishReason - ルール:
STOP以外の値は、特別な処理が必要な異常完了を示します
finishReason の値(Nano Banana シリーズでは IMAGE_ プレフィックスが付いた画像専用の値が追加された点に注意してください):
3. テキストによる拒否説明(重要)
- 位置:
response.candidates[0].content.parts[].text - ルール:
finishReasonがSTOPであるにもかかわらず、partsにtextのみが含まれ画像データが含まれていない場合、API は画像ではなく拒否の説明を返しています。テキストは中国語または英語の場合があります(例):
エラーシナリオ クイックリファレンス
処理フロー(判断順)
コード実装(コア)
上記のチェックを 1 つのパース関数にまとめます:Consumer-Friendly Messaging
Design principles: clear and concise, positive guidance, actionable, no blame. Recommended templates:- Consumer users: by default show only the friendly explanation + revision suggestion
- Business / tool providers: by default expand technical details (
finishReason,candidatesTokenCount, etc.) - Developers: provide an “expand/collapse” toggle to view the full JSON response
ベストプラクティス
- 優先度順に厳密に確認する:
candidatesTokenCount→finishReason→parts→ データを抽出 → キーワード検出 - thoughtSignature を確認する前にテキストを収集する: 拒否理由を失わないようにするためです
- 完全なレスポンスを保持する: 開発/テスト用ツールは、トラブルシューティングのために常に生の JSON を保存してください
- 中国語と英語の拒否テキストをサポートする: Google は中国語または英語を返すことがあるため、キーワード照合では両方をカバーする必要があります
- 段階的にフォールバックする: スマート検出が成功した場合は具体的なメッセージを表示し、それ以外は API テキストをそのまま表示し、それもできなければ親しみやすい
finishReason名を使い、最後に一般的なメッセージへフォールバックします - “unknown error” を表示しない: 常に実行可能な提案か、完全なレスポンスを含めてください
よくある質問
同じ prompt が、成功したり失敗したりするのはなぜですか?
同じ prompt が、成功したり失敗したりするのはなぜですか?
Google の安全フィルタリングにはランダム性と文脈依存があります。参照画像の内容や prompt の組み合わせ方が、いずれも判定に影響します。文言を調整するか、より間接的な表現を試してください。
それがコンテンツの問題か技術的な問題かは、どう見分ければよいですか?
それがコンテンツの問題か技術的な問題かは、どう見分ければよいですか?
candidatesTokenCount: 0 または finishReason: PROHIBITED_CONTENT → コンテンツの問題; Failed to fetch または HTTP エラー → 技術的な問題; API のテキストによる説明 → 通常はコンテンツの問題。一般ユーザーには、どの程度の技術情報を見せるべきですか?
一般ユーザーには、どの程度の技術情報を見せるべきですか?
段階的表示: デフォルトではわかりやすい説明 + 修正提案を表示し、必要に応じて技術詳細を展開し、開発モードでは完全な JSON レスポンスを表示します。
finishReason ごとに個別の処理を書き分ける必要はありますか?
finishReason ごとに個別の処理を書き分ける必要はありますか?
いいえ。マッピング表と汎用フォールバックがあれば十分です:
reasonMessages[finishReason] || のあとに生の値を表示します。