{"record":{"id":"6f90dde8ca2264a9","repo":"alibaba/nacos","slug":"agentversioncatalog-onlineversions-must-be-an-arra","errorCode":null,"errorMessage":"AgentVersionCatalog onlineVersions must be an array","messagePattern":"AgentVersionCatalog onlineVersions 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":342,"sourceCode":"        validateOptionalJsonText(provider, \"url\");\n    }\n    \n    private static void validateExtensionsShape(Map<?, ?> root) {\n        if (root.containsKey(\"extensions\")) {\n            requireJsonObject(root.get(\"extensions\"), \"extensions\");\n        }\n    }\n    \n    private static void validateCatalogShape(Map<?, ?> root) {\n        if (!root.containsKey(\"versionCatalog\")) {\n            throw new IllegalArgumentException(\"Missing AgentResourceExt field: versionCatalog\");\n        }\n        Map<?, ?> catalog = requireJsonObject(root.get(\"versionCatalog\"), \"versionCatalog\");\n        rejectUnknownFields(catalog, CATALOG_FIELDS, \"AgentVersionCatalog\");\n        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)) {","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java#L324-L360","documentation":"Inside the mandatory 'versionCatalog' object, the 'onlineVersions' field must be a JSON array. This check (validateCatalogShape, line 341) fires when onlineVersions is present but is a string, number, object, or null instead of an array. Each array element must itself be an object describing one online Agent Version.","triggerScenarios":"Deserializing ai_resource.ext JSON where versionCatalog.onlineVersions is a non-array type (e.g. a string \"1.0.0\" or an object instead of a list). Triggered during AgentResourceExtSerializer.deserialize → validateJsonShape → validateCatalogShape.","commonSituations":"Typos in hand-written JSON; tools that serialize onlineVersions as a comma-separated string; schema drift from an upstream system that sends versions as a map keyed by version string instead of an array.","solutions":["Change versionCatalog.onlineVersions to a JSON array of objects, each containing 'version', 'labels', and 'protocols'.","Ensure your JSON serializer emits a List/Array type for onlineVersions, not a Map or String.","Run the JSON through AgentResourceExtSerializer.deserialize() in a test to validate the shape before deployment."],"exampleFix":"// before\n\"versionCatalog\":{\"onlineVersions\":{\"version\":\"1.0.0\"}}\n// after\n\"versionCatalog\":{\"onlineVersions\":[{\"version\":\"1.0.0\",\"labels\":[],\"protocols\":[\"a2a\"]}]}","handlingStrategy":"validation","validationCode":"Object onlineVersions = catalogRaw.get(\"onlineVersions\");\nif (!(onlineVersions instanceof List)) {\n    throw new IllegalArgumentException(\"onlineVersions must be a JSON array before deserialization\");\n}","typeGuard":"public static boolean isOnlineVersionsArray(Map<?,?> catalog) {\n    return catalog != null && catalog.get(\"onlineVersions\") instanceof List;\n}","tryCatchPattern":"try {\n    AgentResourceExtSerializer.deserialize(json);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"onlineVersions must be an array\")) {\n        // fix the JSON shape or reject the record\n    }\n    throw e;\n}","preventionTips":["Always serialize onlineVersions as a JSON array, never as a string or object.","Validate the raw JSON shape with a schema validator before calling deserialize().","Use JacksonUtils to serialize typed DTOs so array types are preserved."],"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"}