BerriAI/litellm · error · Exception
The response was blocked by VertexAI. {chunk}
Error message
The response was blocked by VertexAI. {chunk} What it means
Vertex AI branch: when a stream chunk has no text (e.g. 'Part has no text') and the candidate's finish_reason is SAFETY, litellm raises this Exception embedding the raw proto chunk. It means Gemini/Vertex blocked the response with safety filters.
Source
Thrown at litellm/litellm_core_utils/streaming_handler.py:1320
},
"type": "function",
}
],
)
_streaming_response: Final = StreamingChoices(delta=_delta_obj)
_model_response: Final = ModelResponseStream()
_model_response.choices = [_streaming_response]
response_obj = {"original_chunk": _model_response}
else:
raise original_exception
if (
hasattr(chunk.candidates[0], "finish_reason")
and chunk.candidates[0].finish_reason.name != "FINISH_REASON_UNSPECIFIED"
): # every non-final chunk in vertex ai has this
self.received_finish_reason = map_finish_reason(chunk.candidates[0].finish_reason.name)
except Exception:
if chunk.candidates[0].finish_reason.name == "SAFETY":
raise Exception(f"The response was blocked by VertexAI. {chunk}")
else:
completion_obj["content"] = str(chunk)
elif self.custom_llm_provider == "petals":
if self.completion_stream is None or len(self.completion_stream) == 0:
if self.received_finish_reason is not None:
raise StopIteration
else:
self.received_finish_reason = "stop"
chunk_size = 30
stream = cast(Any, self.completion_stream)
new_chunk = stream[:chunk_size]
completion_obj["content"] = new_chunk
self.completion_stream = stream[chunk_size:]
elif self.custom_llm_provider == "palm":
# fake streaming
response_obj = {}
if self.completion_stream is None or len(self.completion_stream) == 0:
if self.received_finish_reason is not None:View on GitHub (pinned to 6c2dcb801b)
Solutions
- Adjust safety_settings per litellm/Vertex docs: set BLOCK_ONLY_HIGH or BLOCK_NONE for the tripped categories (subject to Google allowing relaxation).
- Rephrase the prompt to avoid triggering categories; split sensitive steps into multiple calls.
- Use a model version with different safety posture (e.g. latest Gemini versions).
- Catch this exception and surface a user-facing 'content blocked' message instead of retrying — retrying the same input usually fails again.
Example fix
# before
resp = litellm.completion(model="vertex_ai/gemini-1.5-pro", messages=msgs, stream=True)
# after
resp = litellm.completion(
model="vertex_ai/gemini-1.5-pro", messages=msgs, stream=True,
safety_settings=[
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_ONLY_HIGH"},
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_ONLY_HIGH"},
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_ONLY_HIGH"},
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_ONLY_HIGH"},
],
) Defensive patterns
Strategy: try-catch
Try / catch
try:
for part in stream:
...
except Exception as e:
if "blocked by VertexAI" in str(e):
return ContentBlockedResponse(reason="safety_filter") # do NOT retry same input
raise Prevention
- Set explicit safety_settings thresholds on every Vertex/Gemini call.
- Design UX around safety blocks instead of retry loops; the same input usually re-blocks.
- Log blocked prompts (redacted) to identify which category trips.
When it happens
Trigger: Streaming a Vertex AI (Gemini) model where the prompt or partial generation trips safety filters; candidates carry finishReason=SAFETY and empty parts.
Common situations: Prompts touching violence/medical/self-harm topics; image+text prompts blocked by multimodal filters; default (unrelaxed) safety settings on newer Gemini models being stricter than expected.
Related errors
- Error transforming content delta events: {e}, got message: {
- Braintrust API error: {e.response.text}
- Failed to connect to Braintrust API: {str(e)}
- api_base is required for Pydantic AI agents
- Unexpected responses stream payload
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/b1841a9658d425d2.
Report an issue: GitHub.