Skip to content

ValueError from Python's int_max_str_digits limit escapes generate_content() when the model emits an oversized integer (only JSONDecodeError is guarded in _from_response) #2542

@RichardS83

Description

@RichardS83

Environment

  • python-genai: 1.73.1 (bug still present in 2.7.0, see line refs below)
  • Python: 3.14.3 (any Python ≥ 3.11 with the default int_max_str_digits=4300 is affected)
  • Model: gemini-3-flash-preview

Description

When response_schema / response_json_schema is set, GenerateContentResponse._from_response eagerly parses the response text to populate .parsed:

# google/genai/types.py (v2.7.0, lines 8255, 8282; also 8238, 8271 for the pydantic branches)
try:
    result_text = result._get_text()
    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:
    pass

json.loads can raise more than JSONDecodeError: since Python 3.11 (CVE-2020-10735 mitigation), parsing an integer literal longer than sys.get_int_max_str_digits() (default 4300) raises a plain ValueError:

ValueError: Exceeds the limit (4300 digits) for integer string conversion: value has 25410 digits; use sys.set_int_max_str_digits() to increase the limit

This is not a subclass of JSONDecodeError, so it escapes the guard and propagates out of generate_content() — after the API already returned HTTP 200. The caller cannot distinguish this from an SDK/transport failure, and there is no way to access the response (e.g. .text) because the exception is raised before the response object is returned.

Reproduction

We hit this in production: the model occasionally emits a degenerate/runaway integer literal in structured output (25,410 digits in our case). The application can't prevent that — it's model output. Minimal demonstration of the parsing gap:

import json
try:
    json.loads('{"count": ' + "1" * 5000 + "}")
except json.JSONDecodeError:
    print("handled")          # <- never reached
except ValueError as e:
    print(f"escapes: {e}")    # <- this is what propagates out of generate_content()

Production stack trace (python-genai 1.73.1):

ValueError: Exceeds the limit (4300 digits) for integer string conversion: value has 25410 digits; use sys.set_int_max_str_digits() to increase the limit
  at raw_decode (json/decoder.py:361)
  at decode (json/decoder.py:345)
  at loads (json/__init__.py:352)
  at _from_response (google/genai/types.py:8172)
  at _generate_content (google/genai/models.py:4753)
  at generate_content (google/genai/models.py:6276)

Expected behavior

An unparseable response body (for whatever reason) should degrade the same way a malformed-JSON response does: .parsed stays None and the caller gets the response object back, with .text available for its own error handling.

Suggested fix

json.JSONDecodeError is a subclass of ValueError, so widening the four except json.decoder.JSONDecodeError: clauses in _from_response to except ValueError: keeps the existing behavior and also covers the int-limit case (lines 8238, 8255, 8271, 8282 in v2.7.0).

Metadata

Metadata

Labels

priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions