google/gson · error · NumberFormatException

Expected an int but was " + peekedString + locationString()

Error message

Expected an int but was " + peekedString + locationString()

What it means

Thrown by JsonReader.nextInt() as a NumberFormatException on the fallback path: the value could not be parsed as an int directly (Integer.parseInt failed) and either Double.parseDouble failed (rethrown at line 1371) or the double value loses precision when cast to int (line 1377). The message echoes the offending literal string.

Source

Thrown at gson/src/main/java/com/google/gson/stream/JsonReader.java:1377

        // Fall back to parse as a double below.
      }
    } else {
      throw unexpectedTokenError("an int");
    }

    peeked = PEEKED_BUFFERED;
    double asDouble;
    try {
      asDouble = Double.parseDouble(peekedString);
    } catch (NumberFormatException e) {
      NumberFormatException rethrown =
          new NumberFormatException("Expected an int but was " + peekedString + locationString());
      rethrown.initCause(e);
      throw rethrown;
    }
    result = (int) asDouble;
    if (result != asDouble) { // Make sure no precision was lost casting to 'int'.
      throw new NumberFormatException("Expected an int but was " + peekedString + locationString());
    }
    peekedString = null;
    peeked = PEEKED_NONE;
    pathIndices[stackSize - 1]++;
    return result;
  }

  /**
   * Closes this JSON reader and the underlying {@link Reader}.
   *
   * <p>Using the JSON reader after it has been closed will throw an {@link IllegalStateException}
   * in most cases.
   */
  @Override
  public void close() throws IOException {
    peeked = PEEKED_NONE;
    stack[0] = JsonScope.CLOSED;
    stackSize = 1;

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Use nextString() and parse with Integer.parseInt / NumberFormat yourself, handling failures explicitly.
  2. Use nextDouble() if the value can be fractional.
  3. Sanitize the data source to emit integer literals only.
  4. peek() first; if the token is a STRING, decide whether to coerce or skip.

Example fix

// before
int n = reader.nextInt(); // throws for "1.5" or "abc"

// after
String raw = reader.nextString();
int n = Integer.parseInt(raw); // or NumberFormat.getInstance().parse(raw).intValue()
Defensive patterns

Strategy: validation

Validate before calling

// If the field may be a string or non-integer, read as string and parse defensively
String raw = reader.nextString();
try {
  return Integer.parseInt(raw);
} catch (NumberFormatException e) {
  double d = Double.parseDouble(raw);
  return (int) d; // or handle as needed
}

Try / catch

try {
  return reader.nextInt();
} catch (NumberFormatException e) {
  // log and apply a default, or re-read from the underlying source
  return defaultValue;
}

Prevention

When it happens

Trigger: Calling nextInt() on a quoted string like "abc", a fractional number "1.5", or a value that parses as a double but does not equal its int truncation. Also when the token is a numeric string that is not a valid number at all.

Common situations: Numeric fields that occasionally contain non-numeric or floating-point content; lenient JSON where numbers arrive as strings; schema mismatches; debug/test data with placeholder strings.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/69823b111c05897e.json. Report an issue: GitHub.