apache/dubbo · error · IllegalArgumentException

value '%s' for key '%s' is not a double

Error message

value '%s' for key '%s' is not a double

What it means

Thrown by AbstractJsonUtilImpl.getNumberAsDouble(Map,String) when obj contains key, the value is a String, but Double.parseDouble rejects it (NumberFormatException). This is the string-parse failure path; the method first accepts a true Double, then attempts to parse a String. A value that is neither Double nor String hits a different message (error 190). The exception is an IllegalArgumentException naming the value and key.

Source

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

     * Gets a number from an object for the given key.  If the key is not present, this returns null.
     * If the value does not represent a double, throws an exception.
     */
    @Override
    public Double getNumberAsDouble(Map<String, ?> obj, String key) {
        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }
        Object value = obj.get(key);
        if (value instanceof Double) {
            return (Double) value;
        }
        if (value instanceof String) {
            try {
                return Double.parseDouble((String) value);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                        String.format("value '%s' for key '%s' is not a double", value, key));
            }
        }
        throw new IllegalArgumentException(
                String.format("value '%s' for key '%s' in '%s' is not a number", value, key, obj));
    }

    /**
     * Gets a number from an object for the given key, casted to an integer.  If the key is not
     * present, this returns null.  If the value does not represent an integer, throws an exception.
     */
    @Override
    public Integer getNumberAsInteger(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. Sanitize the string before relying on it (trim, replace locale separators, strip units) or read it from a field guaranteed numeric.
  2. If the field is genuinely free-form, validate with a regex/Double-try before calling getNumberAsDouble and treat non-numeric as a domain error.
  3. Ensure the JSON producer emits numbers (not strings) for numeric fields.
  4. Catch IllegalArgumentException and fall back to a default or report the bad value.

Example fix

// before
Double v = jsonUtil.getNumberAsDouble(obj, "price"); // "12,99"
// after - normalize locale then read
Object raw = obj.get("price");
Double v = raw instanceof Number ? ((Number) raw).doubleValue()
    : Double.parseDouble(((String) raw).replace(',', '.'));
Defensive patterns

Strategy: validation

Validate before calling

Object raw = obj.get(key);
if (raw instanceof String) {
    String s = ((String) raw).trim().replace(',', '.');
    try {
        Double.parseDouble(s); // pre-check parseability
    } catch (NumberFormatException ignored) {
        // not a double; do not call getNumberAsDouble
        return null;
    }
}
return jsonUtil.getNumberAsDouble(obj, key);

Type guard

private static boolean isParsableDouble(Object value) {
    if (value instanceof Double) return true;
    if (value instanceof String) {
        try { Double.parseDouble((String) value); return true; }
        catch (NumberFormatException e) { return false; }
    }
    return false;
}

Try / catch

try {
    return jsonUtil.getNumberAsDouble(obj, key);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("is not a double")) {
        log.warn("non-double string at key={}: {}", key, obj.get(key));
        return null;
    }
    throw e;
}

Prevention

When it happens

Trigger: jsonUtil.getNumberAsDouble(obj, key) where obj.get(key) is a String that is not a valid double — e.g. "abc", "", "NaN-ish", "1,2,3" (comma instead of dot), localized number formats, or a value with surrounding text.

Common situations: Locale-specific decimal separators (comma vs dot); a free-text field misinterpreted as numeric; an empty string where a number was expected; a value like "12px" or "$10" that carries units/currency; whitespace-only strings.

Related errors


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