Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Streaming Tools] Cannot pickle async_generator object #1862

@fbpazos

Description

@fbpazos

Describe the bug
Using the Streaming Tools provided in the official ADK documentation ([guide link](https://google.github.io/adk-docs/streaming/streaming-tools/)), attempting to invoke an async generator (i.e., a function using yield in an async def) within an agent causes a failure due to copy.deepcopy trying to pickle an async_generator. This results in the following error:

TypeError: cannot pickle 'async_generator' object

The crash seems to originate from the session service (in_memory_session_service.py) when it attempts to deepcopy a session that includes an unpickleable async_generator.

To Reproduce

  1. Follow the steps in the [Streaming Tools example](https://google.github.io/adk-docs/streaming/streaming-tools/) as is — no modifications needed.
  2. Alternatively, use the raw code of the example with the LiteLLM integration instead of Google Gemini/Vertex (same result, no need for Google Cloud).
  3. Start the app using adk web.
  4. Trigger an agent tool that includes an async generator.
  5. The error occurs during session loading or response building.

Expected behavior
You'd expect the system to either handle async generators in session state correctly (e.g., skip pickling them), or document that they're unsupported with appropriate guards or error messages.
Instead, it blows up trying to deepcopy an unpickleable async generator, killing the session logic completely.

Screenshots
N/A (see full traceback below instead).

Desktop (please complete the following information):

  • OS: Windows 11
  • Python version (python -V): Python 3.13
  • ADK version (pip show google-adk): google-adk==1.5.0

Model Information
Using a local LiteLLM integration — any local/forwarded model that responds with streaming works. Replacing with real Gemini API is not required to reproduce this.

Additional context
This issue seems to relate to [#586](#586), where someone experienced a similar crash involving deepcopies and unpickleable async content.

The crash is extremely reproducible and baked into the flow, especially for streaming tools. You can't even play with the tutorial code out of the box without tripping over this.
Please either:

  • Avoid storing async_generator objects inside session models
  • Filter them out before deepcopy
  • Or document a proper workaround for tool authors.

Stacktrace

Traceback (most recent call last):
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 409, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        self.scope, self.receive, self.send
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 60, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\fastapi\applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\middleware\errors.py", line 187, in __call__
    raise exc
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\middleware\errors.py", line 165, in __call__
    await self.app(scope, receive, _send)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\middleware\exceptions.py", line 62, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
    raise exc
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\routing.py", line 714, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\routing.py", line 734, in app
    await route.handle(scope, receive, send)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\routing.py", line 288, in handle
    await self.app(scope, receive, send)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\routing.py", line 76, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
    raise exc
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\starlette\routing.py", line 73, in app
    response = await f(request)
               ^^^^^^^^^^^^^^^^
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\fastapi\routing.py", line 301, in app
    raw_response = await run_endpoint_function(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<3 lines>...
    )
    ^
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\fastapi\routing.py", line 212, in run_endpoint_function
    return await dependant.call(**values)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\google\adk\cli\fast_api.py", line 837, in get_event_graph
    session = await session_service.get_session(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        app_name=app_name, user_id=user_id, session_id=session_id
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\google\adk\sessions\in_memory_session_service.py", line 118, in get_session
    return self._get_session_impl(
           ~~~~~~~~~~~~~~~~~~~~~~^
        app_name=app_name,
        ^^^^^^^^^^^^^^^^^^
    ...<2 lines>...
        config=config,
        ^^^^^^^^^^^^^^
    )
    ^
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\google\adk\sessions\in_memory_session_service.py", line 157, in _get_session_impl
    copied_session = copy.deepcopy(session)
  File "C:\Program Files\Python313\Lib\copy.py", line 144, in deepcopy
    y = copier(memo)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\pydantic\main.py", line 940, in __deepcopy__
    _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo))
                                   ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "C:\Program Files\Python313\Lib\copy.py", line 222, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ~~~~~~~~^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "C:\Program Files\Python313\Lib\copy.py", line 197, in _deepcopy_list
    append(deepcopy(a, memo))
           ~~~~~~~~^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 144, in deepcopy
    y = copier(memo)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\pydantic\main.py", line 940, in __deepcopy__
    _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo))
                                   ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "C:\Program Files\Python313\Lib\copy.py", line 222, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ~~~~~~~~^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 144, in deepcopy
    y = copier(memo)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\pydantic\main.py", line 940, in __deepcopy__
    _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo))
                                   ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "C:\Program Files\Python313\Lib\copy.py", line 222, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ~~~~~~~~^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "C:\Program Files\Python313\Lib\copy.py", line 197, in _deepcopy_list
    append(deepcopy(a, memo))
           ~~~~~~~~^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 144, in deepcopy
    y = copier(memo)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\pydantic\main.py", line 940, in __deepcopy__
    _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo))
                                   ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "C:\Program Files\Python313\Lib\copy.py", line 222, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ~~~~~~~~^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 144, in deepcopy
    y = copier(memo)
  File "C:\Users\fbellidopazo\Envs\a2a-adk\Lib\site-packages\pydantic\main.py", line 940, in __deepcopy__
    _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo))
                                   ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "C:\Program Files\Python313\Lib\copy.py", line 222, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ~~~~~~~~^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "C:\Program Files\Python313\Lib\copy.py", line 222, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ~~~~~~~~^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\copy.py", line 152, in deepcopy
    rv = reductor(4)
TypeError: cannot pickle 'async_generator' object

Metadata

Metadata

Assignees

Labels

bot triaged[Bot] This issue is triaged by ADK botlive[Component] This issue is related to live, voice and video chat

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions