From 06871d0c0dd9c08fa50eb6627706dcec13eafe71 Mon Sep 17 00:00:00 2001 From: Yufeng He <40085740+he-yufeng@users.noreply.github.com> Date: Sun, 7 Jun 2026 12:58:51 +0800 Subject: [PATCH] fix: keep responses for oversized JSON integers --- .../tests/models/test_generate_content.py | 25 +++++++++++++++++++ google/genai/types.py | 10 ++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/google/genai/tests/models/test_generate_content.py b/google/genai/tests/models/test_generate_content.py index 8b20d8c66..2141a1d88 100644 --- a/google/genai/tests/models/test_generate_content.py +++ b/google/genai/tests/models/test_generate_content.py @@ -1058,6 +1058,31 @@ class UserProfile(BaseModel): assert response.parsed != None +@pytest.mark.parametrize('schema_key', ['response_schema', 'response_json_schema']) +def test_schema_parse_keeps_response_for_oversized_json_integer( + schema_key, use_vertex, replays_prefix, http_options +): + get_int_max_str_digits = getattr(sys, 'get_int_max_str_digits', None) + if get_int_max_str_digits is None: + pytest.skip('Python runtime has no int string digit limit') + digit_limit = get_int_max_str_digits() + if digit_limit == 0: + pytest.skip('int string digit limit is disabled') + + response_text = '{"count": ' + '1' * (digit_limit + 1) + '}' + response = types.GenerateContentResponse._from_response( + response={ + 'candidates': [ + {'content': {'parts': [{'text': response_text}]}} + ], + }, + kwargs={'config': {schema_key: {'type': 'object'}}}, + ) + + assert response.text == response_text + assert response.parsed is None + + def test_pydantic_schema_orders_properties(client): class Restaurant(BaseModel): name: str diff --git a/google/genai/types.py b/google/genai/types.py index f99fbd070..92995e977 100644 --- a/google/genai/types.py +++ b/google/genai/types.py @@ -8264,7 +8264,7 @@ def _from_response( # may not be a valid json per stream response except pydantic.ValidationError: pass - except json.decoder.JSONDecodeError: + except ValueError: pass elif ( isinstance(response_schema, EnumMeta) and result._get_text() is not None @@ -8296,7 +8296,7 @@ class Placeholder(pydantic.BaseModel): parsed = {'placeholder': json.loads(result_text)} placeholder = Placeholder.model_validate(parsed) result.parsed = placeholder.placeholder - except json.decoder.JSONDecodeError: + except ValueError: pass except pydantic.ValidationError: pass @@ -8312,7 +8312,7 @@ class Placeholder(pydantic.BaseModel): if result_text is not None: result.parsed = json.loads(result_text) # may not be a valid json per stream response - except json.decoder.JSONDecodeError: + except ValueError: pass elif typing.get_origin(response_schema) in _UNION_TYPES: # Union schema. @@ -8329,7 +8329,7 @@ class Placeholder(pydantic.BaseModel): # type: ignore[no-redef] parsed = {'placeholder': json.loads(result_text)} placeholder = Placeholder.model_validate(parsed) result.parsed = placeholder.placeholder - except json.decoder.JSONDecodeError: + except ValueError: pass except pydantic.ValidationError: pass @@ -8339,7 +8339,7 @@ class Placeholder(pydantic.BaseModel): # type: ignore[no-redef] if result_text is not None: result.parsed = json.loads(result_text) # may not be a valid json per stream response - except json.decoder.JSONDecodeError: + except ValueError: pass return result