BlockedPromptException: response was blockedをGoogle Geminiで修正する

intermediate🧠 AI Tools2026-05-17| Python 3.8+、google-generativeai SDK(全バージョン)、Google Gemini API(gemini-pro、gemini-1.5-pro、gemini-2.0-flash)

Error Message

BlockedPromptException: response was blocked
#gemini#safety#blocked#google

TL;DR

BlockedPromptException: response was blocked は、Geminiの安全フィルターがプロンプトまたは生成されたレスポンスをフラグとして検出したことを意味します。どのカテゴリがトリガーされたかを確認するには response.prompt_feedbackcandidate.finish_reason を調べ、safety_settings のしきい値を調整するか、プロンプトを書き直してください。

このエラーが発生する原因

すべてのリクエストは、Geminiが何かを返す前に4つの有害カテゴリを通過します:

  • HARM_CATEGORY_HARASSMENT
  • HARM_CATEGORY_HATE_SPEECH
  • HARM_CATEGORY_SEXUALLY_EXPLICIT
  • HARM_CATEGORY_DANGEROUS_CONTENT

2つの異なる失敗パターンがあります。プロンプト自体がしきい値を超えた場合、1トークンも生成される前に BlockedPromptException が発生します。レスポンスが生成途中でフィルターに引っかかった場合、候補は finish_reason = SAFETY とテキストフィールドが空の状態で返されます。

ステップ1 — 何がブロックされたかを正確に診断する

推測に頼らず、フィードバックオブジェクトを直接読み取りましょう:

import google.generativeai as genai

genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel("gemini-1.5-pro")

try:
    response = model.generate_content("your prompt here")
    print(response.text)
except Exception as e:
    print(f"Exception: {e}")

失敗した場合でも、レスポンスオブジェクトには診断データが含まれています。次のように確認します:

response = model.generate_content("your prompt here", stream=False)

# プロンプトレベルのブロックを確認
print("Prompt feedback:", response.prompt_feedback)

# 候補レベルのブロックを確認
for candidate in response.candidates:
    print("Finish reason:", candidate.finish_reason)
    print("Safety ratings:", candidate.safety_ratings)

ブロックされたプロンプトでは、prompt_feedbackblock_reason に値が入っています。ブロックされたレスポンスでは、候補の finish_reason = FinishReason.SAFETY となり、テキストコンテンツが含まれません。

修正1 — ユースケースに合わせて安全しきい値を下げる

ほとんどのカテゴリのデフォルトしきい値は BLOCK_MEDIUM_AND_ABOVE です。より多くのコンテンツを通過させるには BLOCK_ONLY_HIGH に変更するか、カテゴリを完全に無効にするには BLOCK_NONE を使用します — ただし BLOCK_NONE は許可リストへのAPIアクセスが必要です。

import google.generativeai as genai
from google.generativeai.types import HarmCategory, HarmBlockThreshold

genai.configure(api_key="YOUR_API_KEY")

safety_settings = {
    HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
    HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_ONLY_HIGH,
    HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
    HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
}

model = genai.GenerativeModel(
    model_name="gemini-1.5-pro",
    safety_settings=safety_settings
)

response = model.generate_content("your prompt here")
print(response.text)

しきい値の値(最も厳格から最も緩やかな順):

  • BLOCK_LOW_AND_ABOVE — 低・中・高の深刻度をすべてブロック
  • BLOCK_MEDIUM_AND_ABOVE — ほとんどのカテゴリのデフォルト
  • BLOCK_ONLY_HIGH — 明らかに有害なコンテンツのみブロック
  • BLOCK_NONE — フィルターを無効化(許可リストへのAPIアクセスが必要)

修正2 — フィルターをトリガーしないようにプロンプトを書き直す

安全フィルターがプロンプトをブロックするのは、意図が有害であるためではなく、特定の言い回しがフラグの立ったコンテンツとパターンマッチするためであることが多いです。セキュリティリサーチに関する質問、医療コンテンツ、対立を含むフィクション、武器や化学物質への言及(中立的な文脈でも)は一般的なトリガーです。

以下の書き直し方法が有効です:

  • 明示的なコンテキストを追加する:「ペネトレーションテストレポートのために...」「フィクションのストーリーの中で...」
  • 口語表現の代わりに技術的な表現を使用する
  • 長いプロンプトを小さなピースに分割する — 大きなコンテキストでフィルターをトリガーする文章でも、単独で送信すると通過することが多い
  • 何かを行う方法ではなく、防ぐ方法を尋ねる
# このような書き方はNG(DANGEROUS_CONTENTをトリガーする可能性あり):
prompt = "How do I exploit a buffer overflow vulnerability?"

# 代わりにこのように書く:
prompt = """
I'm writing a secure code review guide. Explain how buffer overflow
vulnerabilities work at a technical level and what input validation
techniques prevent them. Focus on defensive practices.
"""

修正3 — 本番環境でブロックされたレスポンスを適切に処理する

BlockedPromptException でアプリをクラッシュさせるのは適切ではありません。スタックトレースではなく有用な診断情報を表示するフォールバックロジックでコールをラップしましょう:

import google.generativeai as genai
from google.generativeai.types import HarmCategory, HarmBlockThreshold
from google.api_core.exceptions import GoogleAPIError

def safe_generate(model, prompt: str) -> str | None:
    try:
        response = model.generate_content(prompt)

        if not response.candidates:
            block_reason = response.prompt_feedback.block_reason
            print(f"Prompt blocked: {block_reason}")
            return None

        candidate = response.candidates[0]

        if candidate.finish_reason.name == "SAFETY":
            ratings = {r.category.name: r.probability.name
                      for r in candidate.safety_ratings}
            print(f"Response blocked by safety. Ratings: {ratings}")
            return None

        return response.text

    except Exception as e:
        print(f"API error: {e}")
        return None

model = genai.GenerativeModel("gemini-1.5-pro")
result = safe_generate(model, "your prompt here")

if result:
    print(result)
else:
    print("Content could not be generated — review your prompt.")

修正4 — システムインストラクションを使ってコンテキストを設定する

Gemini 1.5以降では、ユーザーメッセージが届く前に永続的なコンテキストを確立するシステムインストラクションを受け付けます。これは、アプリに正当なユースケース — サイバーセキュリティトレーニング、医療教育、フィクション執筆 — があるにもかかわらず、デフォルトの安全設定が脅威と誤解してしまう場合に特に有効です。

model = genai.GenerativeModel(
    model_name="gemini-1.5-pro",
    system_instruction=(
        "You are a cybersecurity training assistant helping developers "
        "understand vulnerabilities for defensive purposes. "
        "Provide technically accurate information suitable for security professionals."
    )
)

修正が機能したか確認する

上記の修正を適用した後、構造化されたチェックを実行します:

response = model.generate_content("your prompt here")

# ブロックされていない場合は空になるはず
print("Block reason:", response.prompt_feedback.block_reason)

# 成功した場合は FinishReason.STOP になるはず
print("Finish reason:", response.candidates[0].finish_reason)

# 実際のコンテンツが含まれているはず
print("Text length:", len(response.text))
print("First 200 chars:", response.text[:200])

正常なレスポンスでは block_reason = 0(ブロックなし)、finish_reason = STOP、そして空でないテキストが表示されます。この3つすべてをパスする必要があります。

何も解決しない場合

しきい値の調整とプロンプトの書き直しを試みてもまだブロックされる場合は、このチェックリストを確認してください:

  • APIティアを確認する — BLOCK_NONE はGoogleからの明示的な許可リスト登録が必要です。Gemini API設定のGoogle Cloudコンソールからアクセスをリクエストしてください。
  • 別のモデルを試す — gemini-2.0-flashgemini-1.5-flashgemini-pro とはデフォルトのしきい値が若干異なり、古いモデルがブロックするプロンプトを通過させる場合があります。
  • Vertex AI SDKに切り替える — Vertex AI経由のエンタープライズデプロイメントは、直接Gemini APIよりも細かい安全制御を公開しています。
  • 使用しているSDKバージョンの公式安全設定ドキュメントを確認する。しきい値のオプションはリリース間で変わるため、0.4.x で機能していた設定が 0.8.x では異なる場合があります。

Related Error Notes