google/gson · error · NumberFormatException
Expected an int but was " + peekedLong + locationString()
Error message
Expected an int but was " + peekedLong + locationString()
What it means
Thrown by JsonReader.nextInt() as a NumberFormatException when the JSON literal was recognized as a complete integer (PEEKED_LONG) but its value does not fit in a Java int. The check `peekedLong != result` after casting to int detects the overflow at JsonReader.java:1335.
Source
Thrown at gson/src/main/java/com/google/gson/stream/JsonReader.java:1336
* Returns the {@link JsonToken#NUMBER int} value of the next token, consuming it. If the next
* token is a string, this method will attempt to parse it as an int. If the next token's numeric
* value cannot be exactly represented by a Java {@code int}, this method throws.
*
* @throws IllegalStateException if the next token is neither a number nor a string.
* @throws NumberFormatException if the next literal value cannot be parsed as a number, or
* exactly represented as an int.
*/
public int nextInt() throws IOException {
int p = peeked;
if (p == PEEKED_NONE) {
p = doPeek();
}
int result;
if (p == PEEKED_LONG) {
result = (int) peekedLong;
if (peekedLong != result) { // Make sure no precision was lost casting to 'int'.
throw new NumberFormatException("Expected an int but was " + peekedLong + locationString());
}
peeked = PEEKED_NONE;
pathIndices[stackSize - 1]++;
return result;
}
if (p == PEEKED_NUMBER) {
peekedString = new String(buffer, pos, peekedNumberLength);
pos += peekedNumberLength;
} else if (p == PEEKED_SINGLE_QUOTED || p == PEEKED_DOUBLE_QUOTED || p == PEEKED_UNQUOTED) {
if (p == PEEKED_UNQUOTED) {
peekedString = nextUnquotedValue();
} else {
peekedString = nextQuotedValue(p == PEEKED_SINGLE_QUOTED ? '\'' : '"');
}
validateAscii(peekedString);
try {
result = Integer.parseInt(peekedString);View on GitHub (pinned to 8b8628c656)
Solutions
- Use nextLong() instead of nextInt() for values that may exceed Integer range.
- Ensure the data source emits values within int range, or switch the field type to long.
- Validate range before reading: peek() and consume as nextLong() then check bounds yourself.
Example fix
// before int count = reader.nextInt(); // throws for 3000000000 // after long count = reader.nextLong();
Defensive patterns
Strategy: validation
Validate before calling
// Read as long first, then range-check for int
long v = reader.nextLong();
if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) {
throw new ArithmeticException("Value " + v + " out of int range");
}
int i = (int) v; Try / catch
try {
return reader.nextInt();
} catch (NumberFormatException e) {
// reposition or re-read as long and handle overflow
throw e;
} Prevention
- Use nextLong() for any field that might exceed Integer range (IDs, timestamps, counters).
- Keep Java field types aligned with the producer's numeric range.
- Add schema validation or range checks before narrowing to int.
- Beware of millisecond timestamps which commonly exceed Integer.MAX_VALUE.
When it happens
Trigger: Calling nextInt() on a JSON number larger than Integer.MAX_VALUE or smaller than Integer.MIN_VALUE, e.g. 3000000000 or -3000000000. The value fits in a long, but the narrowing cast to int changes it, so the precision check fails.
Common situations: 32-bit IDs or counters that have grown beyond Integer range; large counters/timestamps in milliseconds; producer using long IDs while consumer reads nextInt(); porting code from nextLong() to nextInt() without range checks.
Related errors
- Expected a long but was " + peekedString + locationString()
- Expected an int but was " + peekedString + locationString()
- Failed parsing '" + s + "' as BigDecimal; at path " + in.get
- Failed parsing '" + s + "' as BigInteger; at path " + in.get
- Invalid nesting limit: " + limit
AI-assisted analysis of google/gson@8b8628c656 (2026-08-04).
Data as JSON: /data/errors/f6ba52ca65470062.json.
Report an issue: GitHub.