{"record":{"id":"7cd05ed68288e907","repo":"google/gson","slug":"failed-parsing-s-as-biginteger-at-path-pat","errorCode":null,"errorMessage":"Failed parsing '${s}' as BigInteger; at path ${path}","messagePattern":"Failed parsing '(.+?)' as BigInteger; at path (.+?)","errorType":"exception","errorClass":"JsonSyntaxException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java","lineNumber":619,"sourceCode":"        }\n      };\n\n  public static final TypeAdapterFactory BIG_DECIMAL_FACTORY =\n      newFactory(BigDecimal.class, BIG_DECIMAL);\n\n  public static final TypeAdapter<BigInteger> BIG_INTEGER =\n      new TypeAdapter<BigInteger>() {\n        @Override\n        public BigInteger read(JsonReader in) throws IOException {\n          if (in.peek() == JsonToken.NULL) {\n            in.nextNull();\n            return null;\n          }\n          String s = in.nextString();\n          try {\n            return NumberLimits.parseBigInteger(s);\n          } catch (NumberFormatException e) {\n            throw new JsonSyntaxException(\n                \"Failed parsing '\" + s + \"' as BigInteger; at path \" + in.getPreviousPath(), e);\n          }\n        }\n\n        @Override\n        public void write(JsonWriter out, BigInteger value) throws IOException {\n          out.value(value);\n        }\n      };\n\n  public static final TypeAdapterFactory BIG_INTEGER_FACTORY =\n      newFactory(BigInteger.class, BIG_INTEGER);\n\n  public static final TypeAdapter<LazilyParsedNumber> LAZILY_PARSED_NUMBER =\n      new TypeAdapter<LazilyParsedNumber>() {\n        // Normally users should not be able to access and deserialize LazilyParsedNumber because\n        // it is an internal type, but implement this nonetheless in case there are legit corner\n        // cases where this is possible","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java#L601-L637","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","If the value legitimately may contain decimals/commas, change the Java field to BigDecimal or String and convert manually.","Register a custom TypeAdapter<BigInteger> that strips thousands separators or rounds decimals before calling new BigInteger(cleaned).","Sanitize input at the API boundary before handing the JSON to Gson."],"exampleFix":"// before\npublic class Account { public BigInteger balanceMicros; }\n// JSON: {\"balanceMicros\":\"1,000.00\"} -> fails\n\n// after: use BigDecimal or sanitize\npublic class Account {\n  public String balanceMicros; // or BigDecimal\n  public BigInteger asBigInteger() { return new BigInteger(balanceMicros.replaceAll(\"[^0-9-]\",\"\")); }\n}\n\n// or custom adapter:\nGson g = new GsonBuilder()\n  .registerTypeHierarchyAdapter(BigInteger.class, new TypeAdapter<BigInteger>() {\n    public BigInteger read(JsonReader in) throws IOException {\n      String s = in.nextString().replaceAll(\"[,]\",\"\");\n      return new BigInteger(s);\n    }\n    public void write(JsonWriter out, BigInteger v) throws IOException { out.value(v); }\n  }).create();","handlingStrategy":"validation","validationCode":"private static final Pattern BIG_INT = Pattern.compile(\"[+-]?\\\\d+\");\nString raw = jsonNode.get(\"balanceMicros\").getAsString();\nif (!BIG_INT.matcher(raw.trim()).matches()) {\n  throw new IllegalArgumentException(\"Not a BigInteger: \" + raw);\n}\n// now safe to call fromJson or new BigInteger(raw.trim())","typeGuard":null,"tryCatchPattern":"try {\n  return gson.fromJson(json, HasBigInt.class);\n} catch (JsonSyntaxException e) {\n  if (e.getMessage().contains(\"as BigInteger\")) {\n    // log offending path, default, or reject the record\n    throw new IllegalArgumentException(\"Invalid BigInteger in payload\", e);\n  }\n  throw e;\n}","preventionTips":["Validate numeric strings with a [+-]?\\\\d+ regex before deserialization.","Prefer BigDecimal for monetary/decimal payloads to avoid integer-only rejection.","Run contract tests with malformed numbers to ensure the error surfaces clearly.","Sanitize thousands separators/whitespace at the API boundary, not inside Gson."],"tags":["gson","parsing","big-integer","json-syntax-exception","type-adapter"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}