Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Live `AsyncSession.send_tool_response` fails with `TypeError` when `FunctionResponse.parts` carries inline bytes

オープン
#3,022 コメント 1 件 リアクション 0 件 担当者 1 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@Venkaiahbabuneelam がすでに取り組んでいます。

2026年9月30日 から。

  • #3024 @kkkhs による — オープン

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
72/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
python
領域
api

調査の方向性

Start at AsyncSession.send_tool_response and compare its _common.convert_to_dict/json.dumps path with send_client_content's model_dump(mode='json') serialization. Reproduce the no-key example using t.t_tool_response and a FunctionResponse containing inline bytes; done means nested FunctionResponseBlob.data is base64-encoded and parts remain intact, with the deprecated AsyncSession.send path no longer dropping parts or scheduling.

索引モデルが issue の本文から書いたものです。

説明

priority: p2 type: bug
Environment details
  • Programming language: Python 3.14 (also reproduced on 3.10)
  • OS: Linux
  • Package version: google-genai 2.25.0
Steps to reproduce

The Live API's function responses accept multimodal parts, and the Gemini 3.x Live models read an image sent that way. For example, gemini-3.8-live and gemini-3.1-flash-live-preview correctly describe a PNG, JPEG or WebP returned from a tool. However, AsyncSession.send_tool_response can't send such a response. It serializes with _common.convert_to_dict, which leaves FunctionResponseBlob.data as raw bytes, and then passes the result to json.dumps:

import asyncio

from google import genai
from google.genai import types


async def main():
    client = genai.Client()
    tool = types.Tool(function_declarations=[types.FunctionDeclaration(name='take_photo', description='Take a photo.')])
    config = types.LiveConnectConfig(response_modalities=['AUDIO'], tools=[tool])
    async with client.aio.live.connect(model='gemini-3.8-live', config=config) as session:
        await session.send_client_content(
            turns=types.Content(role='user', parts=[types.Part(text='Take a photo and describe it.')])
        )
        async for message in session.receive():
            if message.tool_call:
                call = message.tool_call.function_calls[0]
                await session.send_tool_response(
                    function_responses=types.FunctionResponse(
                        id=call.id,
                        name=call.name,
                        response={'output': 'Photo taken.'},
                        parts=[
                            types.FunctionResponsePart(
                                inline_data=types.FunctionResponseBlob(data=b'\x89PNG...', mime_type='image/png')
                            )
                        ],
                    )
                )
                break


asyncio.run(main())
TypeError: Object of type bytes is not JSON serializable

A minimal repro that needs no API key:

import json

from google.genai import _common, _transformers as t, types

response = types.FunctionResponse(
    id='call_1',
    name='take_photo',
    response={'output': 'Photo taken.'},
    parts=[types.FunctionResponsePart(inline_data=types.FunctionResponseBlob(data=b'\x89PNG', mime_type='image/png'))],
)
json.dumps({'tool_response': _common.convert_to_dict(t.t_tool_response(response), convert_keys=True)})
# TypeError: Object of type bytes is not JSON serializable
Expected behavior

The bytes are base64-encoded, as send_client_content does for Blob.data: it serializes with model_dump(mode='json'), which honors the models' ser_json_bytes='base64'.

Workarounds
  • Serialize the message with the SDK's own types and send it on the session's socket:

    message = types.LiveClientMessage(tool_response=types.LiveClientToolResponse(function_responses=[response]))
    await session._ws.send(message.model_dump_json(by_alias=True, exclude_none=True))
    

    This works, but it reaches into the private _ws.

  • types.FunctionResponseBlob.model_construct(data=base64.b64encode(data).decode(), mime_type=...) also gets the message sent, but convert_to_dict then emits PydanticSerializationUnexpectedValue (Expected bytes) on every call.

Suggested fix

Serialize the tool response the way send_client_content does, with model_dump(mode='json', exclude_none=True), before json.dumps, so that nested bytes are base64-encoded.

The deprecated AsyncSession.send(input=FunctionResponse(...)) path has a related problem. It rebuilds each function response from name, response and id only, so it silently drops parts (and scheduling).

主要言語
Python
スター
4k
フォーク
1k
平均マージ
1日 18時間
マージ済み PR(30日)
52

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

googleapis/python-genai のほかの issue

googleapis/python-genai の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。