alibaba/nacos · error · IllegalArgumentException

{} must be a finite JSON number

Error message

{} must be a finite JSON number

What it means

validateJsonValue() rejects a Float extension value that is NaN or ±Infinity (Float.isFinite is false), because those have no valid JSON representation. Only finite floats are allowed.

Source

Thrown at ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java:179

            bytes = JacksonUtils.toJsonBytes(extensions);
        } catch (NacosSerializationException e) {
            throw new IllegalArgumentException("Unable to serialize Agent extensions", e);
        }
        if (bytes.length > MAX_EXTENSIONS_SIZE) {
            throw new IllegalArgumentException(
                "Agent extensions exceeds " + MAX_EXTENSIONS_SIZE + " bytes");
        }
    }
    
    private static void validateJsonValue(Object value, String fieldName) {
        if (value == null || value instanceof String || value instanceof Boolean
            || value instanceof Byte || value instanceof Short || value instanceof Integer
            || value instanceof Long) {
            return;
        }
        if (value instanceof Float) {
            if (!Float.isFinite((Float) value)) {
                throw new IllegalArgumentException(fieldName + " must be a finite JSON number");
            }
            return;
        }
        if (value instanceof Double) {
            if (!Double.isFinite((Double) value)) {
                throw new IllegalArgumentException(fieldName + " must be a finite JSON number");
            }
            return;
        }
        if (value instanceof Number) {
            return;
        }
        if (value instanceof List) {
            for (Object item : (List<?>) value) {
                validateJsonValue(item, fieldName);
            }
            return;
        }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Sanitize float values before inserting into extensions: replace non-finite with null or a sentinel and skip, or use Double and clamp.
  2. Use Float.isFinite(v) guard and drop/normalize the value if false.
  3. Store precision-sensitive numbers as strings if you need exact representation.

Example fix

// before
ext.put("ratio", numerator / (float) denominator); // denominator 0 -> Infinity

// after
float r = numerator / (float) denominator;
ext.put("ratio", Float.isFinite(r) ? r : null);
Defensive patterns

Strategy: validation

Validate before calling

static Object sanitizeNumber(Object v) {
    return (v instanceof Float && !Float.isFinite((Float) v)) ? null : v;
}
// apply before inserting into extensions

Type guard

static boolean isFiniteJsonNumber(Object v) {
    if (v instanceof Float) return Float.isFinite((Float) v);
    if (v instanceof Double) return Double.isFinite((Double) v);
    return v instanceof Byte || v instanceof Short || v instanceof Integer || v instanceof Long || v instanceof Number;
}

Prevention

When it happens

Trigger: An extensions value is a Float computed from a division by zero, Math operations yielding infinity, or Float.parseFloat("NaN"), then passed into the ext and serialized.

Common situations: Metrics/statistics code writing ratio or score floats into extensions without guarding against infinity; deserialization of a numeric token into Float that overflows.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/3fa2166cbcb55c27. Report an issue: GitHub.