apache/dubbo · error · IllegalArgumentException

value '%s' for key '%s' is not an integer

Error message

value '%s' for key '%s' is not an integer

What it means

Thrown by AbstractJsonUtilImpl.getNumberAsInteger(Map,String) when obj contains key, the value is a String, but Integer.parseInt throws NumberFormatException. This is the string-parse failure path for the integer accessor; the IllegalArgumentException names the value and key. A true Double value is handled separately (error 191 for fractional, success for whole), and non-Double/non-String values hit error 193.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java:161

        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }
        Object value = obj.get(key);
        if (value instanceof Double) {
            Double d = (Double) value;
            int i = d.intValue();
            if (i != d) {
                throw new ClassCastException("Number expected to be integer: " + d);
            }
            return i;
        }
        if (value instanceof String) {
            try {
                return Integer.parseInt((String) value);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                        String.format("value '%s' for key '%s' is not an integer", value, key));
            }
        }
        throw new IllegalArgumentException(String.format("value '%s' for key '%s' is not an integer", value, key));
    }

    /**
     * Gets a number from an object for the given key, casted to an long.  If the key is not
     * present, this returns null.  If the value does not represent a long integer, throws an
     * exception.
     */
    @Override
    public Long getNumberAsLong(Map<String, ?> obj, String key) {
        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }

View on GitHub (pinned to 3a3043227f)

Solutions

  1. If the value may be a decimal string, parse as Double then cast/round: (int) Double.parseDouble(s).
  2. Sanitize the string (strip separators, trim) before relying on it.
  3. If the value may exceed int range, use getNumberAsLong instead.
  4. Align the producer to emit plain integer strings or JSON numbers.

Example fix

// before
Integer n = jsonUtil.getNumberAsInteger(obj, "code"); // "3.0"
// after - tolerate decimal strings
Object raw = obj.get("code");
Integer n = raw instanceof String ? (int) Double.parseDouble((String) raw) : jsonUtil.getNumberAsInteger(obj, "code");
Defensive patterns

Strategy: validation

Validate before calling

Object raw = obj.get(key);
if (raw instanceof String) {
    String s = (String) raw;
    try {
        Integer.parseInt(s); // pre-check
    } catch (NumberFormatException e) {
        // try as decimal then cast
        try { return (int) Double.parseDouble(s); }
        catch (NumberFormatException ignored) { return null; }
    }
}
return jsonUtil.getNumberAsInteger(obj, key);

Type guard

private static boolean isParsableInt(Object value) {
    if (value instanceof Double) return value.equals(Math.rint((Double) value));
    if (value instanceof String) {
        try { Integer.parseInt((String) value); return true; }
        catch (NumberFormatException e) { return false; }
    }
    return false;
}

Try / catch

try {
    return jsonUtil.getNumberAsInteger(obj, key);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("is not an integer")) {
        Object raw = obj.get(key);
        if (raw instanceof String) return (int) Double.parseDouble((String) raw);
    }
    throw e;
}

Prevention

When it happens

Trigger: jsonUtil.getNumberAsInteger(obj, key) where obj.get(key) is a String not parseable as a base-10 int — e.g. "3.5", "abc", "", "1_000", "0x10", a value with a decimal point, or out-of-int-range digits like "99999999999".

Common situations: Numeric field supplied as a decimal string ("3.0") where an int was expected; thousands separators/underscores; hex/scientific notation; a value larger than Integer.MAX_VALUE; free-text where a number was expected; locale formatting.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/14766ad4fb00e18d. Report an issue: GitHub.