apache/dubbo · error · IllegalArgumentException

value ' ' for key ' ' 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.

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.

Appendix: 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)