diff --git a/pydantic_ai_slim/pydantic_ai/models/google.py b/pydantic_ai_slim/pydantic_ai/models/google.py index 094b4b050..f4366ca7a 100644 --- a/pydantic_ai_slim/pydantic_ai/models/google.py +++ b/pydantic_ai_slim/pydantic_ai/models/google.py @@ -304,17 +304,18 @@ async def _generate_content( def _process_response(self, response: GenerateContentResponse) -> ModelResponse: if not response.candidates or len(response.candidates) != 1: raise UnexpectedModelBehavior('Expected exactly one candidate in Gemini response') # pragma: no cover - if response.candidates[0].content is None or response.candidates[0].content.parts is None: - if response.candidates[0].finish_reason == 'SAFETY': + candidate = response.candidates[0] + if candidate.content is None or candidate.content.parts is None: + if candidate.finish_reason == 'SAFETY': raise UnexpectedModelBehavior('Safety settings triggered', str(response)) else: raise UnexpectedModelBehavior( 'Content field missing from Gemini response', str(response) ) # pragma: no cover - parts = response.candidates[0].content.parts or [] + parts = candidate.content.parts or [] vendor_id = response.response_id or None vendor_details: dict[str, Any] | None = None - finish_reason = response.candidates[0].finish_reason + finish_reason = candidate.finish_reason if finish_reason: # pragma: no branch vendor_details = {'finish_reason': finish_reason.value} usage = _metadata_as_usage(response) @@ -437,8 +438,12 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: assert chunk.candidates is not None candidate = chunk.candidates[0] - if candidate.content is None: - raise UnexpectedModelBehavior('Streamed response has no content field') # pragma: no cover + if candidate.content is None or candidate.content.parts is None: + if candidate.finish_reason == 'SAFETY': # pragma: no cover + raise UnexpectedModelBehavior('Safety settings triggered', str(chunk)) + else: + raise UnexpectedModelBehavior('Content field missing from streaming Gemini response', str(chunk)) + assert candidate.content.parts is not None for part in candidate.content.parts: if part.text is not None: