{"record":{"id":"c48c5d2c2dd645a7","repo":"alibaba/nacos","slug":"must-be-an-array","errorCode":null,"errorMessage":"{} must be an array","messagePattern":"(.+?) must be an array","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java","lineNumber":357,"sourceCode":"        validateOptionalJsonText(catalog, \"latestVersion\");\n        Object versionsValue = catalog.get(\"onlineVersions\");\n        if (!(versionsValue instanceof List)) {\n            throw new IllegalArgumentException(\n                \"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\");","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java#L339-L375","documentation":"Inside each versionCatalog.onlineVersions entry, the 'labels' and 'protocols' fields must each be a JSON array. The validateStringArray helper (line 356) throws this when either field is present but is not an array (e.g. a string or number). The field name is interpolated into the message so you know which one failed.","triggerScenarios":"Deserializing ai_resource.ext where a catalog entry's 'labels' or 'protocols' is a non-array JSON value. For example, \"protocols\":\"a2a\" instead of \"protocols\":[\"a2a\"].","commonSituations":"Shorthand notation where a single protocol or label is written as a bare string; schema migration from a format that used comma-separated strings; incorrect client-side DTO mapping.","solutions":["Wrap the value in square brackets: change \"protocols\":\"a2a\" to \"protocols\":[\"a2a\"].","If the field should be absent, omit it entirely rather than using a non-array placeholder.","Ensure your DTO serializes List<String> fields as JSON arrays."],"exampleFix":"// before\n{\"version\":\"1.0.0\",\"labels\":\"stable\",\"protocols\":\"a2a\"}\n// after\n{\"version\":\"1.0.0\",\"labels\":[\"stable\"],\"protocols\":[\"a2a\"]}","handlingStrategy":"validation","validationCode":"private static void ensureStringArray(Map<?,?> entry, String field) {\n    Object value = entry.get(field);\n    if (value != null && !(value instanceof List)) {\n        throw new IllegalArgumentException(field + \" must be an array\");\n    }\n}","typeGuard":"public static boolean isStringArrayField(Map<?,?> obj, String field) {\n    Object value = obj == null ? null : obj.get(field);\n    return value instanceof List;\n}","tryCatchPattern":"try {\n    AgentResourceExtSerializer.deserialize(json);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().endsWith(\"must be an array\")) {\n        // identify the field from the message and fix the JSON\n    }\n    throw e;\n}","preventionTips":["Always use JSON arrays for labels and protocols, even for single values.","Validate with a JSON Schema that enforces type: array for these fields.","Test deserialization with representative payloads in CI."],"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"}