| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
The _make_json_serializable fallback delegated wholesale to pydantic_core.to_jsonable_python, which raises on deferred Pydantic models (e.g. GroundingMetadata with MockValSer under google-genai 2.18+) before serialize_unknown can apply, aborting event serialization and the enclosing invocation. Walk the structure and convert each leaf under try/except, falling back to repr with a warning naming the affected paths, so the fallback can never raise. Fixes google#6848
| Back | FazBrowse Home | New Git URL |
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
This is the complementary defense-in-depth fix discussed in the #6848 thread
(agreed with @andrewrfitz and acknowledged by @llalitkumarrr): #6849 fixes the
root cause by force-building deferred Pydantic serializers; this PR makes the
serialization fallback itself resilient so a deferred model can never kill the
invocation, even if it reaches serialization.
Problem:
When google-genai >= 2.18 leaves a MockValSer placeholder on a
GroundingMetadata produced via nested validation (defer_build=True),
serializing that value with to_jsonable_python(value, serialize_unknown=True)
raises TypeError before serialize_unknown can apply. The whole
state_delta / agent_state fallback then crashes, aborting
merge_parallel_function_response_events when a search tool runs in parallel
with another tool.
Solution:
Rewrite _make_json_serializable to walk dicts/lists recursively and convert
each leaf individually under try/except, replacing only the raising values
with their repr and logging a warning that names the affected paths. Healthy
input produces output byte-identical to to_jsonable_python (enforced by a
parity test), so the existing serializers that honor callers'
exclude/include directives are unaffected. Container subclasses with broken
iteration also fall back to repr instead of escaping.
Testing Plan
Unit Tests:
New tests reproduce the exact failure shape from the issue — a Pydantic model
whose __pydantic_serializer__ is a placeholder (_DeferredModel with
__pydantic_serializer__ = object()) — at the root, in dicts, nested in
containers, and inside state_delta / agent_state via model_dump(mode='json').
Manual End-to-End (E2E) Tests:
The issue reproduces without a model call or API key, and the deferred-model
unit tests exercise the same serialization path (EventActions.model_dump
→ wrap serializer → fallback) that crashes in
merge_parallel_function_response_events. No E2E setup beyond the unit suite
is needed for this change; the root-cause behavior is additionally covered by
#6849.
Checklist
Additional context