Managing Integer String Conversion Limits
Markdown--- name: managing-integer-string-conversion-limits description: Explains and resolves Python's integer-string conversion length limitation (int/str conversion digit cap introduced for DoS protection). Use when encountering ValueError about "Exceeds the limit for integer string conversion", converting very large integers to/from strings, or configuring sys.set_int_max_str_digits. ---
If you hit this error:
ValueError: Exceeds the limit (4300 digits) for integer string conversion: value has 5000 digits
Fix it by raising or disabling the limit before the conversion happens:
Pythonimport sys sys.set_int_max_str_digits(20000) # raise limit # or sys.set_int_max_str_digits(0) # disable limit entirely (0 = no limit) print(str(10**10000)) # now works
Python limits int <-> str conversions to prevent quadratic-time DoS attacks when converting huge integers (conversion is O(n²) in digit count). This applies to:
str(int),repr(int),f"{n}","%d" % nint(str),int(s, base=10)- Any implicit conversion going through these paths
Default limit: 4300 digits (roughly a number with ~14000 bits). This is intentionally set above what most legitimate programs need but low enough to block abuse.
Not affected: non-decimal bases (hex(), oct(), bin(), int(s, 16), etc.) — the limit only applies to base-10 conversions since those are the ones with quadratic blowup risk.
Progress:
- Identify whether the error comes from legitimate large-number use or a bug producing runaway integers
- Decide: raise the limit, disable it, or fix the underlying issue
- Apply the fix at the right scope (interpreter, module, or command line)
- Verify no security regression if disabling in a public-facing service
Option 1: Command line
python -X int_max_str_digits=0 script.py
Option 2: Environment variable
PYTHONINTMAXSTRDIGITS=0 python script.py
Option 3: Programmatic (must run before any large conversion)
Pythonimport sys sys.set_int_max_str_digits(0) # or specific integer >= 640
Check current limit
Pythonsys.get_int_max_str_digits()
Setting must be 0 (no limit) or an integer >= 640. Lower values raise ValueError.
Example 1 — legitimate math (factorials, big computations): Input:
Pythonimport math str(math.factorial(3000))
Output: Raises ValueError (factorial(3000) has >4300 digits). Fix:
Pythonimport sys, math sys.set_int_max_str_digits(0) str(math.factorial(3000)) # works
Example 2 — parsing untrusted input (should keep the limit): Input:
Pythonint(user_supplied_string) # user_supplied_string is 1,000,000 chars of digits
Output: Raises ValueError by default — this is the intended protection. Do not disable the limit here; instead validate/reject oversized input before parsing.
Example 3 — library needs a higher limit only temporarily:
Pythonimport sys old = sys.get_int_max_str_digits() sys.set_int_max_str_digits(0) try: result = str(big_int) finally: sys.set_int_max_str_digits(old)
- Set the limit as early as possible (top of
main, or via-X/env var) — changing it mid-conversion doesn't help retroactively. - Prefer the command-line/env-var approach for whole-program policy; use
sys.set_int_max_str_digits()for library-level, scoped adjustments. - If writing a library that legitimately needs big-int string conversion, don't silently call
set_int_max_str_digits(0)globally — this weakens protection for the whole process, including unrelated code. Save/restore the previous value. - For services parsing untrusted input, keep the default limit (or set something explicit and low) — the whole point is DoS protection against attacker-supplied huge numeric strings.
- Non-decimal conversions (
hex,bin,oct) are unaffected — use them if you don't actually need decimal representation.
- Setting the limit after the conversion call already executed (order matters — it's a global interpreter setting checked at call time).
- Disabling the limit globally in server/web code that parses user-provided numeric strings — reintroduces the DoS vector this feature exists to prevent.
- Assuming the limit affects
int(s, 16)or similar — it only applies to base-10 conversions. - Forgetting that
f"{n}"and%-formatting also go through the same limited conversion path, not juststr()/int().