Gemini HARM_CATEGORY Threshold Configuration — Fix (2026) | AI Error Hub
GeminiSafetySeverity: LowHTTP 400

Gemini HARM_CATEGORY Threshold Configuration

You're passing safety_settings but seeing invalid category names, unsupported thresholds, or configurations that don't behave as expected. Fix by using correct enum values, understanding threshold levels, and knowing which categories can be adjusted.

Error code: INVALID_ARGUMENTHTTP: 400Category: SafetyLast tested: Nov 15, 2026
Quick Fix (TL;DR)

Categories: HARM_CATEGORY_HARASSMENT, HATE_SPEECH, SEXUALLY_EXPLICIT, DANGEROUS_CONTENT, CIVIC_INTEGRITY. Thresholds: BLOCK_NONE, BLOCK_ONLY_HIGH, BLOCK_MEDIUM_AND_ABOVE (default), BLOCK_LOW_AND_ABOVE. Use exact strings, per-category settings. CSAM and severe harm always blocked regardless.

The Error Messages You're Seeing

Response body variants
HTTP/1.1 400 Bad Request

{
  "error": {
    "code": 400,
    "message": "Invalid HarmCategory: 'HARM_CATEGORY_VIOLENCE' 
    is not a valid enum value.",
    "status": "INVALID_ARGUMENT"
  }
}

Variants:
"Invalid HarmBlockThreshold: 'BLOCK_HIGH' not valid"
"Duplicate safety setting for HARM_CATEGORY_DANGEROUS_CONTENT"
"HARM_CATEGORY_CIVIC_INTEGRITY threshold not adjustable in 
this region"
"safety_settings not permitted on unblockable models"

Threshold Levels Reference

ThresholdBlocks at probabilityUse when
BLOCK_LOW_AND_ABOVELOW, MEDIUM, HIGHKids' apps, strict compliance
BLOCK_MEDIUM_AND_ABOVEMEDIUM, HIGH (default)General purpose apps
BLOCK_ONLY_HIGHHIGH onlyAdult content platforms, research
BLOCK_NONENothing (via safety_settings)Approved research, moderation tools
OFF (alternative)Filter disabled entirelySame as BLOCK_NONE for most

Category Adjustability

CategoryAdjustableNotes
HARM_CATEGORY_HARASSMENTYesAll thresholds
HARM_CATEGORY_HATE_SPEECHYesAll thresholds
HARM_CATEGORY_SEXUALLY_EXPLICITYesAll thresholds
HARM_CATEGORY_DANGEROUS_CONTENTYesExtreme content always blocked regardless
HARM_CATEGORY_CIVIC_INTEGRITYLimitedRegion/model dependent
CSAM (implicit)NoAlways blocked

What Actually Causes This Error

35%
Invented category namesUsing HARM_CATEGORY_VIOLENCE (doesn't exist) or old names.
22%
Wrong threshold enumBLOCK_HIGH or BLOCK_MEDIUM aren't valid — full names required.
18%
Duplicate category entriesSame category listed twice in settings array.
12%
Trying to adjust unadjustableCSAM implicit filter can't be modified via API.
8%
Case mismatchSending "block_none" or "Block_None" instead of BLOCK_NONE.
5%
CIVIC_INTEGRITY on wrong regionFeature availability varies by deployment.

Fixes That Work (Tested Nov 2026)

1Correct Configuration Syntax

Python · well-formed safety_settings
from google import genai from google.genai import types client = genai.Client() # For adult content platforms — loosen sexual filter only adult_config = types.GenerateContentConfig( safety_settings=[ types.SafetySetting( category="HARM_CATEGORY_SEXUALLY_EXPLICIT", 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_DANGEROUS_CONTENT", threshold="BLOCK_MEDIUM_AND_ABOVE" ) ] ) # For kids' education app — max protection kids_config = types.GenerateContentConfig( safety_settings=[ types.SafetySetting(category=c, threshold="BLOCK_LOW_AND_ABOVE") for c in [ "HARM_CATEGORY_HARASSMENT", "HARM_CATEGORY_HATE_SPEECH", "HARM_CATEGORY_SEXUALLY_EXPLICIT", "HARM_CATEGORY_DANGEROUS_CONTENT", ] ] )

2Context-Specific Configurations

Python · profiles per use case
SAFETY_PROFILES = { "default": { "HARM_CATEGORY_HARASSMENT": "BLOCK_MEDIUM_AND_ABOVE", "HARM_CATEGORY_HATE_SPEECH": "BLOCK_MEDIUM_AND_ABOVE", "HARM_CATEGORY_SEXUALLY_EXPLICIT": "BLOCK_MEDIUM_AND_ABOVE", "HARM_CATEGORY_DANGEROUS_CONTENT": "BLOCK_MEDIUM_AND_ABOVE", }, "security_research": { "HARM_CATEGORY_DANGEROUS_CONTENT": "BLOCK_ONLY_HIGH", "HARM_CATEGORY_HARASSMENT": "BLOCK_MEDIUM_AND_ABOVE", "HARM_CATEGORY_HATE_SPEECH": "BLOCK_MEDIUM_AND_ABOVE", "HARM_CATEGORY_SEXUALLY_EXPLICIT": "BLOCK_MEDIUM_AND_ABOVE", }, "medical_education": { "HARM_CATEGORY_DANGEROUS_CONTENT": "BLOCK_ONLY_HIGH", "HARM_CATEGORY_HARASSMENT": "BLOCK_MEDIUM_AND_ABOVE", "HARM_CATEGORY_HATE_SPEECH": "BLOCK_MEDIUM_AND_ABOVE", "HARM_CATEGORY_SEXUALLY_EXPLICIT": "BLOCK_ONLY_HIGH", }, "strict_kids": { cat: "BLOCK_LOW_AND_ABOVE" for cat in [ "HARM_CATEGORY_HARASSMENT", "HARM_CATEGORY_HATE_SPEECH", "HARM_CATEGORY_SEXUALLY_EXPLICIT", "HARM_CATEGORY_DANGEROUS_CONTENT", ] } } def build_safety_config(profile_name): settings = SAFETY_PROFILES[profile_name] return [ types.SafetySetting(category=cat, threshold=th) for cat, th in settings.items() ] config = types.GenerateContentConfig( safety_settings=build_safety_config("security_research") )
Document why you loosen thresholds

If your app permits BLOCK_ONLY_HIGH or BLOCK_NONE on any category, document the business justification in code comments and a policy doc. Legal, PR, and compliance teams will ask; auditors will look.

3Inspect Safety Ratings Post-Response

Python · log probability distributions
import logging logger = logging.getLogger("gemini.safety") def log_safety_signals(response): """Log rating probabilities for tuning threshold decisions.""" if not response.candidates: return candidate = response.candidates[0] for rating in (candidate.safety_ratings or []): logger.info( "category=%s probability=%s blocked=%s", rating.category, rating.probability, getattr(rating, "blocked", False) ) # Analysis: over time, count # - which categories fire most # - probability distribution (mostly LOW? then thresholds may be too tight) # - blocked / total ratio per category # - tune profile based on real user data

Preventing This Error Going Forward

  • Use SDK constants when possible. Prevents typos.
  • Never duplicate category entries. One SafetySetting per category.
  • Log rating probabilities to tune thresholds. Data-driven, not guesswork.
  • Document loose thresholds in code + policy. Justify each deviation.
  • Test all thresholds against your real content. Especially non-English.
  • Remember: severe harm always blocked. Even at BLOCK_NONE.
AR
Tested by Ahmed R.
Researcher · AI Error Hub
Last verified: Nov 15, 2026 · SDK: google-genai 0.8+

Frequently Asked Questions

For the adjustable categories yes — model may produce content that would have been blocked at default. But core unblockable filters (CSAM, imminent violence toward identified persons) remain active regardless.

Same category names and threshold enums. Vertex AI historically allowed lower defaults for enterprise workloads; the API accepts identical configuration. Model behavior may differ slightly between deployment paths.

Doesn't exist as a separate category. Violence-related content evaluated under HARM_CATEGORY_DANGEROUS_CONTENT (instructions to harm) or HARM_CATEGORY_HARASSMENT (targeting people).

Curate a labeled test set of prompts across your content spectrum. Run through Gemini, log probabilities, check block rates against expectations. Iterate. Consider AI Studio playground for interactive testing.

Safety runs independently. A blocked response with structured outputs configured will still produce empty content + SAFETY finish_reason. Handle both response_schema parse failures AND safety blocks in your code.