Repository: pydantic/pydantic-ai

Issue #897: Got pydantic_core._pydantic_core.ValidationError: 1 validation error for list[typed-dict] after stream_structured() with gemini-1.5-flash
Created: 2025-02-11T18:47:17Z
Description
I am facing an issue when running prompts like asking the current date (with a date() tool that returns a string) with gemini-1.5-flash.
This happens "randomly" and I am trying to write a minimal working example to identify when this mostly happens. I have noted the issue when I'm streaming the response using Result.stream_structured() (see traceback below).
Traceback
[2025-02-11 13:19:53] [ WARNING] (root) - Error running agent 'test_agent' with model gemini-1.5-flash: 1 validation error for list[typed-dict]
  Invalid JSON: invalid unicode code point at line 27 column 23 [type=json_invalid, input_value=bytearray(b'[{\n  "candid...        "text": " \xc3'), input_type=bytearray]
    For further information visit https://errors.pydantic.dev/2.10/v/json_invalid (_wrapper.py:134)
Traceback (most recent call last):
  File "/app/chat/agents/_agents/_wrapper.py", line 131, in run_stream
    yield result
  File "/app/chat/api.py", line 99, in process_prompt_and_stream_messages
    async for model_response, last_message in result.stream_structured():
    ...<4 lines>...
            yield data
  File "/usr/local/lib/python3.13/site-packages/pydantic_ai/result.py", line 319, in stream_structured
    async for _events in group_iter:
        msg = self._stream_response.get()
        yield msg, False
  File "/usr/local/lib/python3.13/site-packages/pydantic_ai/_utils.py", line 150, in async_iter_groups
    item = done.pop().result()
  File "/usr/local/lib/python3.13/site-packages/pydantic_ai/models/gemini.py", line 321, in _get_event_iterator
    async for gemini_response in self._get_gemini_responses():
    ...<24 lines>...
                assert 'function_response' in gemini_part, f'Unexpected part: {gemini_part}'
  File "/usr/local/lib/python3.13/site-packages/pydantic_ai/models/gemini.py", line 359, in _get_gemini_responses
    gemini_responses = _gemini_streamed_response_ta.validate_json(
        self._content,
        experimental_allow_partial='trailing-strings',
    )
  File "/usr/local/lib/python3.13/site-packages/pydantic/type_adapter.py", line 446, in validate_json
    return self.validator.validate_json(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        data, strict=strict, context=context, allow_partial=experimental_allow_partial
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
pydantic_core._pydantic_core.ValidationError: 1 validation error for list[typed-dict]
  Invalid JSON: invalid unicode code point at line 27 column 23 [type=json_invalid, input_value=bytearray(b'[{\n  "candid...        "text": " \xc3'), input_type=bytearray]
    For further information visit https://errors.pydantic.dev/2.10/v/json_invalid

Duplicate issue #939: VertexAIModel 'invalid unicode code point', when parsing response
Created: 2025-02-17T17:07:07Z
to reproduce:

use the chat_app.py example
change to use gemini via vertex:
model = VertexAIModel('gemini-1.5-flash', region='europe-west1')
agent = Agent(model)
# agent = Agent('openai:gpt-4o')

type 'hello' in web ui



watch it fail to parse what i assume is an emoji?

    | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "/Users/ben/Library/Caches/uv/archive-v0/FN0WeVkRv7NpSxT07zg-q/lib/python3.12/site-packages/starlette/responses.py", line 264, in wrap
    |     await func()
    |   File "/Users/ben/Library/Caches/uv/archive-v0/FN0WeVkRv7NpSxT07zg-q/lib/python3.12/site-packages/starlette/responses.py", line 245, in stream_response
    |     async for chunk in self.body_iterator:
    |   File "/Users/ben/code/scratch/pydantic-agent-test/chat_app.py", line 140, in stream_messages
    |     async for text in result.stream(debounce_by=0.01):
    |   File "/Users/ben/Library/Caches/uv/archive-v0/FN0WeVkRv7NpSxT07zg-q/lib/python3.12/site-packages/pydantic_ai/result.py", line 217, in stream
    |     async for structured_message, is_last in self.stream_structured(debounce_by=debounce_by):
    |   File "/Users/ben/Library/Caches/uv/archive-v0/FN0WeVkRv7NpSxT07zg-q/lib/python3.12/site-packages/pydantic_ai/result.py", line 319, in stream_structured
    |     async for _events in group_iter:
    |   File "/Users/ben/Library/Caches/uv/archive-v0/FN0WeVkRv7NpSxT07zg-q/lib/python3.12/site-packages/pydantic_ai/_utils.py", line 150, in async_iter_groups
    |     item = done.pop().result()
    |            ^^^^^^^^^^^^^^^^^^^
    |   File "/Users/ben/Library/Caches/uv/archive-v0/FN0WeVkRv7NpSxT07zg-q/lib/python3.12/site-packages/pydantic_ai/models/gemini.py", line 334, in _get_event_iterator
    |     async for gemini_response in self._get_gemini_responses():
    |   File "/Users/ben/Library/Caches/uv/archive-v0/FN0WeVkRv7NpSxT07zg-q/lib/python3.12/site-packages/pydantic_ai/models/gemini.py", line 372, in _get_gemini_responses
    |     gemini_responses = _gemini_streamed_response_ta.validate_json(
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/Users/ben/Library/Caches/uv/archive-v0/FN0WeVkRv7NpSxT07zg-q/lib/python3.12/site-packages/pydantic/type_adapter.py", line 446, in validate_json
    |     return self.validator.validate_json(
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | pydantic_core._pydantic_core.ValidationError: 1 validation error for list[typed-dict]
    |   Invalid JSON: invalid unicode code point at line 57 column 24 [type=json_invalid, input_value=bytearray(b'[{\n  "candid...       "text": "! \xf0'), input_type=bytearray]
    |     For further information visit https://errors.pydantic.dev/2.10/v/json_invalid
    +------------------------------------

Closing comment (2025-02-17T21:41:11Z): The issue may be related to #897, which @dmontagu fixed.

agreed, ive replicated on my side that the bytestream is getting cut half way thru a multi-byte emoji. what a nightmare to track down!