google/gson · error · JsonSyntaxException

Failed parsing '${s}' as BigInteger; at path ${path}

Error message

Failed parsing '${s}' as BigInteger; at path ${path}

What it means

Thrown by Gson's built-in BigInteger TypeAdapter when the JSON value cannot be parsed by NumberLimits.parseBigInteger. Gson reads the token as a string (so it accepts both JSON numbers and JSON strings) and delegates to BigInteger parsing; if the text contains non-numeric characters, exponents in unsupported form, or is empty, a NumberFormatException is wrapped as a JsonSyntaxException pinpointing the offending path.

Source

Thrown at gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java:619

        }
      };

  public static final TypeAdapterFactory BIG_DECIMAL_FACTORY =
      newFactory(BigDecimal.class, BIG_DECIMAL);

  public static final TypeAdapter<BigInteger> BIG_INTEGER =
      new TypeAdapter<BigInteger>() {
        @Override
        public BigInteger read(JsonReader in) throws IOException {
          if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
          }
          String s = in.nextString();
          try {
            return NumberLimits.parseBigInteger(s);
          } catch (NumberFormatException e) {
            throw new JsonSyntaxException(
                "Failed parsing '" + s + "' as BigInteger; at path " + in.getPreviousPath(), e);
          }
        }

        @Override
        public void write(JsonWriter out, BigInteger value) throws IOException {
          out.value(value);
        }
      };

  public static final TypeAdapterFactory BIG_INTEGER_FACTORY =
      newFactory(BigInteger.class, BIG_INTEGER);

  public static final TypeAdapter<LazilyParsedNumber> LAZILY_PARSED_NUMBER =
      new TypeAdapter<LazilyParsedNumber>() {
        // Normally users should not be able to access and deserialize LazilyParsedNumber because
        // it is an internal type, but implement this nonetheless in case there are legit corner
        // cases where this is possible

View on GitHub (pinned to 310ac341f2)

Solutions

  1. Inspect the 'at path' location in the error and fix the source JSON so the value is an integer string like "123" or a JSON integer number.
  2. If the value legitimately may contain decimals/commas, change the Java field to BigDecimal or String and convert manually.
  3. Register a custom TypeAdapter<BigInteger> that strips thousands separators or rounds decimals before calling new BigInteger(cleaned).
  4. Sanitize input at the API boundary before handing the JSON to Gson.

Example fix

// before
public class Account { public BigInteger balanceMicros; }
// JSON: {"balanceMicros":"1,000.00"} -> fails

// after: use BigDecimal or sanitize
public class Account {
  public String balanceMicros; // or BigDecimal
  public BigInteger asBigInteger() { return new BigInteger(balanceMicros.replaceAll("[^0-9-]","")); }
}

// or custom adapter:
Gson g = new GsonBuilder()
  .registerTypeHierarchyAdapter(BigInteger.class, new TypeAdapter<BigInteger>() {
    public BigInteger read(JsonReader in) throws IOException {
      String s = in.nextString().replaceAll("[,]","");
      return new BigInteger(s);
    }
    public void write(JsonWriter out, BigInteger v) throws IOException { out.value(v); }
  }).create();
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern BIG_INT = Pattern.compile("[+-]?\\d+");
String raw = jsonNode.get("balanceMicros").getAsString();
if (!BIG_INT.matcher(raw.trim()).matches()) {
  throw new IllegalArgumentException("Not a BigInteger: " + raw);
}
// now safe to call fromJson or new BigInteger(raw.trim())

Try / catch

try {
  return gson.fromJson(json, HasBigInt.class);
} catch (JsonSyntaxException e) {
  if (e.getMessage().contains("as BigInteger")) {
    // log offending path, default, or reject the record
    throw new IllegalArgumentException("Invalid BigInteger in payload", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Deserializing JSON into a field/element of type java.math.BigInteger (or Map<BigInteger, ...>) where the JSON value is non-numeric (e.g. "abc", "", "NaN", "1.5" with fractional part that BigInteger rejects, or an object/array token that the reader coerced). Also triggered when a JSON number has a floating exponent/sign that BigInteger cannot represent.

Common situations: Sending a decimal/floating value like 3.14 into a BigInteger field; receiving IDs from an upstream service that quotes numbers as strings with stray characters; locale-specific formatting (commas as thousands separators e.g. "1,000"); mistakenly mapping a BigInteger field onto a JSON object.

Related errors


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