fix: handle ValueError and RecursionError in _safe_json_serialize#5414
fix: handle ValueError and RecursionError in _safe_json_serialize#5414voidborne-d wants to merge 2 commits intogoogle:mainfrom
Conversation
17dc740 to
87499ee
Compare
|
Hi @voidborne-d , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Please fix formatting errors by running autoformat.sh |
87499ee to
ddff034
Compare
55145ae to
5b20085
Compare
Both _safe_json_serialize implementations only catch TypeError and OverflowError from json.dumps, but json.dumps can also raise: - ValueError: circular references (e.g. object referencing itself) - RecursionError: deeply nested structures exceeding recursion limit In telemetry/tracing.py, this is especially critical because _safe_json_serialize is called inside a finally block during trace_tool_call — an unhandled exception here can suppress the original tool execution result. In models/lite_llm.py, an unhandled exception during message serialization causes hard LLM request construction failures where a graceful fallback is expected. Fix: - Add ValueError and RecursionError to the exception tuple in both implementations. - In lite_llm.py, wrap the str() fallback in a secondary try/except RecursionError since str() can also fail on deeply recursive objects. 8 regression tests added across both modules. Fixes google#5411 Fixes google#5412
67cee5d to
c231cf8
Compare
|
Rebased onto current main (c231cf8). Upstream now catches
Tests in Mergeable now (was |
Summary
Both
_safe_json_serializeimplementations only catchTypeErrorandOverflowErrorfromjson.dumps, butjson.dumpscan also raise:ValueError: circular references (e.g.obj.ref = obj)RecursionError: deeply nested structures exceeding Python's recursion limitImpact
telemetry/tracing.py(critical):_safe_json_serializeis called inside afinallyblock duringtrace_tool_call. An unhandled exception here can suppress the original tool execution result — telemetry failures should never affect runtime correctness.models/lite_llm.py: An unhandled exception during message serialization causes hard LLM request construction failures where a graceful fallback is expected.Root Cause
The
exceptclause catches(TypeError, OverflowError)but notValueErrororRecursionError. Both are documentedjson.dumpsfailure modes:ValueErrorfor circular references (per Python docs)RecursionErrorfor structures exceedingsys.getrecursionlimit()Note: in
tracing.py, thedefault=lambda o: ...callback handlesTypeErrorfor individual non-serializable objects, but circular references and deep recursion bypass thedefaultcallback entirely.Fix
ValueErrorandRecursionErrorto the exception tuple in both implementations.lite_llm.py, wrap thestr()fallback in a secondarytry/except RecursionErrorsincestr()→__repr__()can also fail on deeply recursive objects.Reproduction
Tests
8 regression tests added across both modules:
test_safe_json_serialize.py(telemetry): circular ref, deep nesting, normal dict, non-serializable objecttest_litellm_safe_serialize.py(models): circular ref, deep nesting, normal dict, non-serializable objectAll 8 tests pass.
Fixes #5411
Fixes #5412