alibaba/nacos · error · IllegalArgumentException

{} must contain only strings

Error message

{} must contain only strings

What it means

Inside each versionCatalog.onlineVersions entry, every element of the 'labels' and 'protocols' arrays must be a JSON string. The validateStringArray helper (line 360) throws this when an array element is a number, boolean, object, or null. This ensures the catalog only stores string-tagged data.

Source

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

                "AgentVersionCatalog onlineVersions must be an array");
        }
        for (Object entryValue : (List<?>) versionsValue) {
            Map<?, ?> entry = requireJsonObject(entryValue, "versionCatalog entry");
            rejectUnknownFields(entry, CATALOG_ENTRY_FIELDS, "AgentVersionCatalogEntry");
            validateRequiredJsonText(entry, "version");
            validateStringArray(entry, "labels");
            validateStringArray(entry, "protocols");
        }
    }
    
    private static void validateStringArray(Map<?, ?> object, String field) {
        Object value = object.get(field);
        if (!(value instanceof List)) {
            throw new IllegalArgumentException(field + " must be an array");
        }
        for (Object item : (List<?>) value) {
            if (!(item instanceof String)) {
                throw new IllegalArgumentException(field + " must contain only strings");
            }
        }
    }
    
    private static Map<?, ?> requireJsonObject(Object value, String fieldName) {
        if (!(value instanceof Map)) {
            throw new IllegalArgumentException(fieldName + " must be a JSON object");
        }
        return (Map<?, ?>) value;
    }
    
    private static void validateRequiredJsonText(Map<?, ?> object, String field) {
        if (!(object.get(field) instanceof String)) {
            throw new IllegalArgumentException(field + " must be a string");
        }
    }
    
    private static void validateOptionalJsonText(Map<?, ?> object, String field) {

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Convert every element in the labels/protocols arrays to a quoted JSON string.
  2. Audit the producer code that builds these arrays to ensure only String values are added.
  3. Use AgentResourceExtSerializer.deserialize() in integration tests to catch type mismatches early.

Example fix

// before
{"version":"1.0.0","protocols":["a2a",42]}
// after
{"version":"1.0.0","protocols":["a2a","42"]}
Defensive patterns

Strategy: validation

Validate before calling

private static void ensureAllStrings(List<?> list, String field) {
    for (Object item : list) {
        if (!(item instanceof String)) {
            throw new IllegalArgumentException(field + " contains non-string: " + item);
        }
    }
}

Type guard

public static boolean isStringArray(List<?> list) {
    if (list == null) return false;
    for (Object item : list) {
        if (!(item instanceof String)) return false;
    }
    return true;
}

Try / catch

try {
    AgentResourceExtSerializer.deserialize(json);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("must contain only strings")) {
        // sanitize the array: convert all elements to strings
    }
    throw e;
}

Prevention

When it happens

Trigger: Deserializing ai_resource.ext where a catalog entry's 'labels' or 'protocols' array contains a non-string element, e.g. [123] or [true] or [{"key":"val"}].

Common situations: Numeric protocol codes or boolean flags mistakenly placed in the protocols/labels arrays; automated JSON generators that emit unquoted values; schema confusion with metadata maps that allow mixed types.

Related errors


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