google/gson · error · NumberFormatException

Number string too large: ${s.substring(0, 30)}...

Error message

Number string too large: ${s.substring(0, 30)}...

What it means

NumberLimits enforces a 10,000-character cap on number strings parsed from JSON to prevent algorithmic-complexity attacks (BigDecimal/BigInteger parsing is superlinear). Strings exceeding MAX_NUMBER_STRING_LENGTH throw NumberFormatException with a 30-char preview (NumberLimits.java:16).

Source

Thrown at gson/src/main/java/com/google/gson/internal/NumberLimits.java:17

package com.google.gson.internal;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * This class enforces limits on numbers parsed from JSON to avoid potential performance problems
 * when extremely large numbers are used.
 */
public final class NumberLimits {
  private NumberLimits() {}

  private static final int MAX_NUMBER_STRING_LENGTH = 10_000;

  private static void checkNumberStringLength(String s) {
    if (s.length() > MAX_NUMBER_STRING_LENGTH) {
      throw new NumberFormatException("Number string too large: " + s.substring(0, 30) + "...");
    }
  }

  public static BigDecimal parseBigDecimal(String s) throws NumberFormatException {
    checkNumberStringLength(s);
    BigDecimal decimal = new BigDecimal(s);

    // Cast to long to avoid issues with abs when value is Integer.MIN_VALUE
    if (Math.abs((long) decimal.scale()) >= 10_000) {
      throw new NumberFormatException("Number has unsupported scale: " + s);
    }
    return decimal;
  }

  public static BigInteger parseBigInteger(String s) throws NumberFormatException {
    checkNumberStringLength(s);
    return new BigInteger(s);
  }

View on GitHub (pinned to 310ac341f2)

Solutions

  1. Validate input length before parsing and reject/truncate at the trust boundary.
  2. If you genuinely need huge numbers, pre-process the JSON to express them as quoted strings and parse with an explicit, bounded parser.
  3. Cap request body size upstream so such payloads never reach the parser.

Example fix

// before
BigDecimal v = NumberLimits.parseBigDecimal(hugeNumberString);
// after
if (hugeNumberString.length() > 10_000) throw new IllegalArgumentException("number too large");
BigDecimal v = NumberLimits.parseBigDecimal(hugeNumberString);
Defensive patterns

Strategy: validation

Validate before calling

private static final int MAX = 10_000;
if (s != null && s.length() > MAX) throw new NumberFormatException("number string too large");
BigDecimal d = NumberLimits.parseBigDecimal(s);

Type guard

static boolean withinLength(String s) { return s != null && s.length() <= 10_000; }

Try / catch

try { NumberLimits.parseBigDecimal(s); } catch (NumberFormatException e) { /* too large or malformed */ }

Prevention

When it happens

Trigger: Calling NumberLimits.parseBigDecimal or parseBigInteger (or Gson paths that funnel through them, e.g. LazilyParsedNumber.asBigDecimal / big-decimal coercion) on a JSON number with more than 10,000 characters.

Common situations: Processing untrusted JSON containing adversarial huge numbers; binary blobs encoded as numeric strings; misformatted scientific-notation fields with absurd exponents; accidental concatenation producing very long numeric strings.

Related errors


AI-assisted analysis of google/gson@310ac341f2 (2026-08-10). Data as JSON: /api/errors/5551e757e034dc59. Report an issue: GitHub.