{"record":{"id":"e86856a7903cff2f","repo":"alibaba/nacos","slug":"must-contain-only-strings","errorCode":null,"errorMessage":"{} must contain only strings","messagePattern":"(.+?) must contain only strings","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java","lineNumber":361,"sourceCode":"                \"AgentVersionCatalog onlineVersions must be an array\");\n        }\n        for (Object entryValue : (List<?>) versionsValue) {\n            Map<?, ?> entry = requireJsonObject(entryValue, \"versionCatalog entry\");\n            rejectUnknownFields(entry, CATALOG_ENTRY_FIELDS, \"AgentVersionCatalogEntry\");\n            validateRequiredJsonText(entry, \"version\");\n            validateStringArray(entry, \"labels\");\n            validateStringArray(entry, \"protocols\");\n        }\n    }\n    \n    private static void validateStringArray(Map<?, ?> object, String field) {\n        Object value = object.get(field);\n        if (!(value instanceof List)) {\n            throw new IllegalArgumentException(field + \" must be an array\");\n        }\n        for (Object item : (List<?>) value) {\n            if (!(item instanceof String)) {\n                throw new IllegalArgumentException(field + \" must contain only strings\");\n            }\n        }\n    }\n    \n    private static Map<?, ?> requireJsonObject(Object value, String fieldName) {\n        if (!(value instanceof Map)) {\n            throw new IllegalArgumentException(fieldName + \" must be a JSON object\");\n        }\n        return (Map<?, ?>) value;\n    }\n    \n    private static void validateRequiredJsonText(Map<?, ?> object, String field) {\n        if (!(object.get(field) instanceof String)) {\n            throw new IllegalArgumentException(field + \" must be a string\");\n        }\n    }\n    \n    private static void validateOptionalJsonText(Map<?, ?> object, String field) {","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java#L343-L379","documentation":"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.","triggerScenarios":"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\"}].","commonSituations":"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.","solutions":["Convert every element in the labels/protocols arrays to a quoted JSON string.","Audit the producer code that builds these arrays to ensure only String values are added.","Use AgentResourceExtSerializer.deserialize() in integration tests to catch type mismatches early."],"exampleFix":"// before\n{\"version\":\"1.0.0\",\"protocols\":[\"a2a\",42]}\n// after\n{\"version\":\"1.0.0\",\"protocols\":[\"a2a\",\"42\"]}","handlingStrategy":"validation","validationCode":"private static void ensureAllStrings(List<?> list, String field) {\n    for (Object item : list) {\n        if (!(item instanceof String)) {\n            throw new IllegalArgumentException(field + \" contains non-string: \" + item);\n        }\n    }\n}","typeGuard":"public static boolean isStringArray(List<?> list) {\n    if (list == null) return false;\n    for (Object item : list) {\n        if (!(item instanceof String)) return false;\n    }\n    return true;\n}","tryCatchPattern":"try {\n    AgentResourceExtSerializer.deserialize(json);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"must contain only strings\")) {\n        // sanitize the array: convert all elements to strings\n    }\n    throw e;\n}","preventionTips":["Ensure producer code only adds String values to labels and protocols lists.","Use typed List<String> in DTOs so the compiler catches mixed-type additions.","Validate JSON payloads with a schema that specifies items: {type: string}."],"tags":["validation","ai-agent","json-schema","serialization"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}