python/cpython · error · ValueError

cannot convert string of len {lenS} to int

Error message

cannot convert string of len {lenS} to int

What it means

Raised by the asymptotically fast int-from-decimal-string path in _pylong (used for huge string conversion via decimal arithmetic) when the input string is so large that estimating its digit count with IEEE-754 doubles loses too much precision: the estimated word count w needs >= 46 bits, leaving fewer than ~7 bits of float mantissa headroom. The message reports the offending string length.

Source

Thrown at Lib/_pylong.py:363

    # finite-precision floating point for this, it's possible that the
    # computed value is a little less than the true value. If the true
    # value is at - or a little higher than - an integer, we can get an
    # off-by-1 error too low. So we add 2 instead of 1 if chopping lost
    # a fraction > 0.9.

    # The "WASI" test platform can complain about `len(s)` if it's too
    # large to fit in its idea of "an index-sized integer".
    lenS = s.__len__()
    log_ub = lenS * _LOG_10_BASE_256
    log_ub_as_int = int(log_ub)
    w = log_ub_as_int + 1 + (log_ub - log_ub_as_int > 0.9)
    # And what if we've plain exhausted the limits of HW floats? We
    # could compute the log to any desired precision using `decimal`,
    # but it's not plausible that anyone will pass a string requiring
    # trillions of bytes (unless they're just trying to "break things").
    if w.bit_length() >= 46:
        # "Only" had < 53 - 46 = 7 bits to spare in IEEE-754 double.
        raise ValueError(f"cannot convert string of len {lenS} to int")
    with decimal.localcontext(_unbounded_dec_context) as ctx:
        D256 = D(256)
        pow256 = compute_powers(w, D256, BYTELIM, need_hi=True)
        rpow256 = compute_powers(w, 1 / D256, BYTELIM, need_hi=True)
        # We're going to do inexact, chopped arithmetic, multiplying by
        # an approximation to the reciprocal of 256**i. We chop to get a
        # lower bound on the true integer quotient. Our approximation is
        # a lower bound, the multiplication is chopped too, and
        # to_integral_value() is also chopped.
        ctx.traps[decimal.Inexact] = 0
        ctx.rounding = decimal.ROUND_DOWN
        for k, v in pow256.items():
            # No need to save much more precision in the reciprocal than
            # the power of 256 has, plus some guard digits to absorb
            # most relevant rounding errors. This is highly significant:
            # 1/2**i has the same number of significant decimal digits
            # as 5**i, generally over twice the number in 2**i,
            ctx.prec = v.adjusted() + GUARD + 1

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Validate input length before conversion and reject absurd sizes: if len(s) > 10**8: raise ValueError('number too large')
  2. Cap decompression and read sizes so a crafted blob cannot become a trillion-digit string
  3. Find why such a huge 'number' exists at all — it indicates an upstream parsing bug (reading the wrong field or the wrong file)

Example fix

# before
value = int(request_data)   # request_data is attacker-controlled, may be huge

# after
MAX_DIGITS = 10**6
if len(request_data) > MAX_DIGITS:
    raise ValueError('numeric input too long')
value = int(request_data)
Defensive patterns

Strategy: validation

Validate before calling

MAX_DIGITS = 10**8  # 100M digits is already absurd
if len(s) > MAX_DIGITS:
    raise ValueError(f'numeric string too long: {len(s)} digits')
value = int(s)

Type guard

def is_reasonable_numeric_string(s):
    return isinstance(s, (str, bytes)) and len(s) <= 10**8

Try / catch

try:
    value = int(s)
except ValueError as e:
    if 'cannot convert string of len' in str(e):
        raise ValueError('input too large to be a legitimate number') from e
    raise

Prevention

When it happens

Trigger: int(huge_string) where huge_string has on the order of 10**13+ characters (trillions of digits) — the guard only trips for absurd inputs; len(s) * _LOG_10_BASE_256 overflows float precision such that w.bit_length() >= 46.

Common situations: Almost exclusively adversarial/buggy programs: unvalidated network or decompressed input fed straight into int(); a size/length field misparsed so a multi-terabyte buffer is treated as a number; test fuzzing with giant numeric strings.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/38b41f26ea48aa88. Report an issue: GitHub.