{"record":{"id":"4baaaa43e7eb9118","repo":"pydantic/monty","slug":"exceeds-the-limit-int-max-str-digits-digits-for-integer","errorCode":null,"errorMessage":"Exceeds the limit ({INT_MAX_STR_DIGITS} digits) for integer string conversion: value has {digit_count} digits; use sys.set_int_max_str_digits() to increase the limit","messagePattern":"Exceeds the limit \\((.+?) digits\\) for integer string conversion: value has (.+?) digits; use sys\\.set_int_max_str_digits\\(\\) to increase the limit","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"crates/monty/src/modules/json/load.rs","lineNumber":340,"sourceCode":"        }));\n    }\n    Ok(())\n}\n\n/// Converts `jiter`'s oversized-integer parse error into CPython's digit-limit\n/// `ValueError` when the offending token is a decimal integer literal.\nfn json_number_out_of_range_to_run_error(error: &JiterError, bytes: &[u8]) -> Option<RunError> {\n    if error.error_type != JiterErrorType::JsonError(JsonErrorType::NumberOutOfRange) {\n        return None;\n    }\n\n    let token = slice_json_number_around(bytes, error.index);\n    if !is_json_integer_token(token) {\n        return None;\n    }\n\n    let digit_count = decimal_digit_count_ascii(token);\n    check_decimal_digit_count(digit_count).err()\n}\n\n/// Returns whether a raw JSON number token is an integer literal rather than a\n/// float or exponent form.\nfn is_json_integer_token(token: &[u8]) -> bool {\n    !token.is_empty() && !token.contains(&b'.') && !token.contains(&b'e') && !token.contains(&b'E')\n}\n\n/// Returns the JSON number token that surrounds `index`.\n///\n/// `jiter` reports `NumberOutOfRange` at or just after the failing position, so\n/// this scans outward to recover the original token for CPython-compatible\n/// integer digit-limit handling.\nfn slice_json_number_around(bytes: &[u8], index: usize) -> &[u8] {\n    let mut start = index.min(bytes.len());\n    while start > 0 && is_json_number_byte(bytes[start - 1]) {\n        start -= 1;\n    }","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty/src/modules/json/load.rs#L322-L358","documentation":"Monty's JSON loader (`crates/monty/src/modules/json/load.rs:340`, in `json_number_out_of_range_to_run_error`, reached via `parse_json_bytes`) enforces CPython's `sys.set_int_max_str_digits` limit (4300 digits) when a JSON number literal is a decimal integer token with too many digits. It raises Python's `ValueError` with CPython's exact message, so `json.loads('1234...')` fails identically to CPython instead of producing an arbitrarily huge int. Float/exponent tokens are exempt (they parse as float); only plain integer literals are limited.","triggerScenarios":"Calling `json.loads()` (or the bytes variant) on input containing an integer literal with more digits than `sys.get_int_max_str_digits()` (default 4300), e.g. a long numeric ID, key, or hash embedded as a bare JSON number.","commonSituations":"Parsing API responses or data dumps where 64-bit+ IDs were serialized as JSON numbers and later padded with zeros or concatenated, pushing the literal past 4300 digits; code that worked on other engines but must match CPython's int-str conversion limit.","solutions":["In sandboxed Python code, call `sys.set_int_max_str_digits(0)` (disable) or a higher limit before `json.loads`.","Quote the value as a JSON string (e.g. `\"123456789...\"`) and convert with `int(s)` semantics as needed — string keys/IDs should never be bare numbers.","Strip leading zeros or truncate the literal in preprocessing so it stays under the digit limit.","If the huge number is legitimate data, decode it as a float by adding `.0` or an exponent (float tokens bypass the int digit limit)."],"exampleFix":"// before\nconst data = JSON.parse(hugeIntJson);\n\n// after\nimport sys\nif hasattr(sys, 'set_int_max_str_digits'):\n    sys.set_int_max_str_digits(0)\ndata = json.loads(huge_int_json)","handlingStrategy":"validation","validationCode":"import sys\n\ndef json_safe(obj):\n    if isinstance(obj, str) and obj.isdigit() and len(obj) > sys.get_int_max_str_digits():\n        raise ValueError('integer literal exceeds int_max_str_digits; pass it as a string')\n    return obj\n\ndef check_json_ints(text):\n    import json\n    for m in __import__('re').finditer(r'(?<![.eE\\d])\\d+', text):\n        if len(m.group()) > (sys.get_int_max_str_digits() or 4300):\n            raise ValueError(f'JSON integer literal has {len(m.group())} digits')","typeGuard":null,"tryCatchPattern":"import sys\ntry:\n    data = json.loads(raw)\nexcept ValueError as exc:\n    if 'set_int_max_str_digits' in str(exc):\n        sys.set_int_max_str_digits(0)\n        data = json.loads(raw)\n    else:\n        raise","preventionTips":["Serialize IDs and hashes as JSON strings, never bare numbers.","Call sys.set_int_max_str_digits early in sandbox code that ingests third-party JSON.","Keep integer literals in data pipelines under the 4300-digit default; check data sources for zero-padded numerics."],"tags":["python","json","valueerror","integer-limit","cpython-parity"],"backgroundTag":"value-out-of-range","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}