Gemini Safety Filter Blocked Response (SAFETY) — Fix (2026) | AI Error Hub
GeminiSafetySeverity: Mediumfinish_reason=SAFETY

Gemini Safety Filter Blocked Response

Your response has finish_reason: "SAFETY" and empty content — Gemini's safety system blocked either the prompt or the output. Check prompt_feedback.block_reason for prompt blocks or safety_ratings on the candidate for output blocks. Handle gracefully in your UX.

Detection: finish_reason === "SAFETY"Category: SafetyCommon cause: Content policy violationLast tested: Nov 15, 2026
Quick Fix (TL;DR)

Two block types: (1) prompt block — response has no candidates, check prompt_feedback.block_reason; (2) output block — candidate exists but empty content, finish_reason: "SAFETY", check candidate.safety_ratings. Adjust safety_settings thresholds for legitimate use cases, or rephrase to avoid triggers.

The Symptoms You're Seeing

Response variants
# Prompt block — no candidates at all
response.candidates = []
response.prompt_feedback.block_reason = "SAFETY"
response.prompt_feedback.safety_ratings = [
  {"category": "HARM_CATEGORY_HARASSMENT", "probability": "HIGH"},
  ...
]

# Output block — candidate exists, empty content
response.candidates[0].finish_reason = "SAFETY"
response.candidates[0].content = None  # or empty parts
response.candidates[0].safety_ratings = [
  {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "probability": "MEDIUM", "blocked": true},
  ...
]

# Attempting response.text raises:
ValueError: Cannot get text from candidate with no valid Parts.

Harm Categories & Block Reasons

CategoryMeaningTypical triggers
HARM_CATEGORY_HARASSMENTTargeting individuals or groupsPersonal attacks, bullying language
HARM_CATEGORY_HATE_SPEECHSlurs, discriminationProtected class targeting
HARM_CATEGORY_SEXUALLY_EXPLICITSexual contentExplicit descriptions
HARM_CATEGORY_DANGEROUS_CONTENTInstructions for harmWeapons, drugs, self-harm details
HARM_CATEGORY_CIVIC_INTEGRITYElection/civic disinformationFake voting info, election fraud claims
block_reason values: SAFETY, OTHER, BLOCKLIST, PROHIBITED_CONTENT, IMAGE_SAFETY

What Actually Causes This Error

30%
User content directly violates policyActual policy-triggering material submitted.
25%
False positives on legitimate useMedical, security, historical discussions.
20%
Default thresholds too strictBLOCK_MEDIUM_AND_ABOVE default is aggressive.
12%
Model output drifted into sensitive territoryFine input, output moved to policy zone.
8%
Multilingual triggersContent in Urdu/Arabic triggers differently than English.
5%
Adversarial jailbreak attemptsUser trying to extract disallowed content.

Fixes That Work (Tested Nov 2026)

1Robust Response Handler

Python · check both block types
from google import genai client = genai.Client() def safe_generate(model, contents, config=None): response = client.models.generate_content( model=model, contents=contents, config=config ) # CHECK 1: prompt block (no candidates) if not response.candidates: pf = response.prompt_feedback return { "status": "prompt_blocked", "block_reason": pf.block_reason if pf else "UNKNOWN", "safety_ratings": pf.safety_ratings if pf else [], "user_message": "Your prompt was blocked by our safety system." } candidate = response.candidates[0] finish = str(candidate.finish_reason) # CHECK 2: output block if "SAFETY" in finish: blocked_categories = [ r.category for r in (candidate.safety_ratings or []) if getattr(r, "blocked", False) ] return { "status": "output_blocked", "blocked_categories": blocked_categories, "user_message": "The response was stopped by our safety filter." } # CHECK 3: other terminations if "MAX_TOKENS" in finish: return {"status": "truncated", "content": response.text} if "RECITATION" in finish: return {"status": "recitation_blocked", "content": None} return {"status": "success", "content": response.text}

2Adjust Safety Thresholds

Python · loosen for legitimate contexts
from google.genai import types # Threshold levels (loosest to strictest): # BLOCK_NONE ← disables filter # BLOCK_ONLY_HIGH ← permits low/medium # BLOCK_MEDIUM_AND_ABOVE ← default # BLOCK_LOW_AND_ABOVE ← strictest # Example: medical/security research context config = types.GenerateContentConfig( safety_settings=[ types.SafetySetting( category="HARM_CATEGORY_DANGEROUS_CONTENT", threshold="BLOCK_ONLY_HIGH" ), types.SafetySetting( category="HARM_CATEGORY_HARASSMENT", threshold="BLOCK_MEDIUM_AND_ABOVE" ), types.SafetySetting( category="HARM_CATEGORY_HATE_SPEECH", threshold="BLOCK_MEDIUM_AND_ABOVE" ), types.SafetySetting( category="HARM_CATEGORY_SEXUALLY_EXPLICIT", threshold="BLOCK_MEDIUM_AND_ABOVE" ) ] ) response = client.models.generate_content( model="gemini-2.5-flash", contents="Explain how buffer overflows work for CTF training", config=config )
Vertex AI vs AI Studio threshold defaults

AI Studio defaults are stricter than Vertex AI for most categories. Vertex allows finer configuration and lower thresholds by default in enterprise contexts. If migrating, expect different block rates.

3User-Facing Remediation

Python · graceful UX
CATEGORY_TO_MESSAGE = { "HARM_CATEGORY_HARASSMENT": "Your message could be interpreted as harassing.", "HARM_CATEGORY_HATE_SPEECH": "Your message contains language that may be discriminatory.", "HARM_CATEGORY_SEXUALLY_EXPLICIT": "Your message contains sexual content not allowed here.", "HARM_CATEGORY_DANGEROUS_CONTENT": "Your message may enable harm.", "HARM_CATEGORY_CIVIC_INTEGRITY": "Your message may contain election-related misinformation.", } def explain_block(safety_result): if safety_result["status"] == "prompt_blocked": return { "kind": "prompt", "reason": str(safety_result["block_reason"]), "advice": "Try rephrasing without sensitive framing." } if safety_result["status"] == "output_blocked": cats = safety_result["blocked_categories"] messages = [CATEGORY_TO_MESSAGE.get(str(c), str(c)) for c in cats] return { "kind": "output", "reasons": messages, "advice": "Reformulate your question for a different response." } return None

Preventing This Error Going Forward

  • Always check for empty candidates first. Prompt blocks return no candidates.
  • Never call response.text without checking finish_reason. Raises on blocks.
  • Adjust safety_settings for your domain context. Medical, education, security research.
  • Log block category + probability. Tune thresholds from data.
  • Show user-friendly, non-scary messages. Not "ERROR" — explain what to do.
  • Provide crisis resources for self-harm context. Don't just block silently.
  • Never set all thresholds to BLOCK_NONE. Legal + reputational risk.
SK
Tested by Sana K.
Researcher · AI Error Hub
Last verified: Nov 15, 2026 · SDK: google-genai 0.8+

Frequently Asked Questions

You can set most categories to BLOCK_NONE — but Google's core content moderation (CSAM, extreme violence, etc.) remains regardless. Setting NONE is intended for specific approved use cases; document why in your code and consider legal/PR risk.

Yes for input tokens. Output tokens generated before the block also billed. Prompt blocks (no generation) typically bill only input.

Input and output moderation are independent. Model may generate content that scores higher than the input on some category. Common in creative writing where scenes escalate. Adjust output category thresholds if legitimate.

No — RECITATION means model output closely reproduced copyrighted training material and was blocked separately. Different from SAFETY (content policy). Can't be disabled via safety_settings.

Aimed at election-specific disinformation (fake voting locations, fraud claims), not general political discussion. Normal political conversation isn't typically blocked. Adjust category threshold if false positives.