google/gson · error · NumberFormatException
Expected an int but was {}{}
Error message
Expected an int but was {}{} What it means
Thrown by JsonReader.nextInt() (JsonReader.java:1334-1337) when the literal was recognized as a PEEKED_LONG (an integer literal that fit in a long) but does not fit in an int: (int) peekedLong != peekedLong. It is a NumberFormatException indicating an overflow when narrowing a valid long to int. The reader refuses to silently truncate.
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 310ac341f2)
Solutions
- Use nextLong() for fields that may exceed Integer.MAX_VALUE.
- Validate magnitude before reading, or guard with try/catch NumberFormatException and fall back to nextLong.
- Update the consuming field type from int to long.
- Check the JSON schema/producer for the field's numeric range.
Example fix
// before int id = reader.nextInt(); // fails on 9007199254740993 // after long id = reader.nextLong();
Defensive patterns
Strategy: validation
Validate before calling
// If the value may exceed Integer.MAX_VALUE, read as long. long v = reader.nextLong(); int narrowed = (int) v; // explicit, only if you accept truncation
Type guard
static boolean fitsInInt(long v) {
return v >= Integer.MIN_VALUE && v <= Integer.MAX_VALUE;
} Try / catch
try {
return reader.nextInt();
} catch (NumberFormatException e) {
return Math.toIntExact(reader.nextLong());
} Prevention
- Use nextLong for id/timestamp fields that may grow past int range.
- Document the numeric range of each field at the schema level.
- Add tests with boundary values (Integer.MAX_VALUE, MAX_VALUE+1).
When it happens
Trigger: Calling nextInt() on a JSON number larger than Integer.MAX_VALUE (2147483647) or smaller than Integer.MIN_VALUE, e.g. 9007199254740993 or a 64-bit id field read into an int.
Common situations: Reading a field that grew beyond int range over time (e.g. snowflake ids, timestamps in millis); schema mismatch where the producer emits 64-bit ids but the consumer calls nextInt; assuming a count fits in int.
Related errors
- Expected a long but was {}{}
- Invalid nesting limit: {}
- JsonReader is closed
- Nesting limit {} reached{}
- End of input{}
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/580e3850fefd529d.
Report an issue: GitHub.