{"record":{"id":"b09a4d6ef7f08538","repo":"alibaba/nacos","slug":"agent-version-catalog-must-use-descending-version","errorCode":null,"errorMessage":"Agent Version catalog must use descending Version order","messagePattern":"Agent Version catalog must use descending Version order","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java","lineNumber":218,"sourceCode":"                if (!(entry.getKey() instanceof String)) {\n                    throw new IllegalArgumentException(\n                        fieldName + \" contains a non-string JSON object key\");\n                }\n                validateJsonValue(entry.getValue(), fieldName);\n            }\n            return;\n        }\n        throw new IllegalArgumentException(fieldName + \" is not a JSON value\");\n    }\n    \n    private static void validateCatalog(AgentVersionCatalog catalog) {\n        AgentModelValidator.validateVersionCatalog(catalog);\n        List<AgentVersionCatalogEntry> versions = catalog.getOnlineVersions();\n        for (int i = 1; i < versions.size(); i++) {\n            String previous = versions.get(i - 1).getVersion();\n            String current = versions.get(i).getVersion();\n            if (AgentVersionComparator.compare(previous, current) <= 0) {\n                throw new IllegalArgumentException(\n                    \"Agent Version catalog must use descending Version order\");\n            }\n        }\n    }\n    \n    private static void validateOptionalAbsoluteUri(String value, String fieldName) {\n        if (value == null) {\n            return;\n        }\n        if (value.isEmpty() || value.codePointCount(0, value.length()) > MAX_URI_LENGTH) {\n            throw new IllegalArgumentException(\"Invalid \" + fieldName);\n        }\n        try {\n            URI uri = new URI(value);\n            if (!uri.isAbsolute()) {\n                throw new IllegalArgumentException(fieldName + \" must be an absolute URI\");\n            }\n        } catch (URISyntaxException e) {","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java#L200-L236","documentation":"validateCatalog() requires onlineVersions to be strictly descending by semantic version (AgentVersionComparator). For each adjacent pair, the previous must compare greater-than the current; if previous <= current (equal or out of order) the ext is rejected. This enforces a canonical, newest-first ordering.","triggerScenarios":"An agent create/update whose versionCatalog.onlineVersions is unsorted, ascending, or contains duplicate versions. Triggered on serialize before persist and on deserialize when reading back.","commonSituations":"Appending a new version to the end of the list (which is oldest-first), inserting a patch version out of order, or duplicates from a merge.","solutions":["Sort onlineVersions in descending order before publishing: versions.sort((a,b) -> AgentVersionComparator.compare(b.getVersion(), a.getVersion())).","De-duplicate versions before sorting.","Verify ordering with the same comparator you will publish under."],"exampleFix":"// before\ncatalog.setOnlineVersions(List.of(v(\"1.0.0\"), v(\"2.0.0\"), v(\"1.5.0\"))); // not descending\n\n// after\nList<AgentVersionCatalogEntry> vs = new ArrayList<>(List.of(v(\"1.0.0\"), v(\"2.0.0\"), v(\"1.5.0\")));\nvs.sort((a, b) -> AgentVersionComparator.compare(b.getVersion(), a.getVersion()));\ncatalog.setOnlineVersions(vs); // [2.0.0, 1.5.0, 1.0.0]","handlingStrategy":"validation","validationCode":"List<AgentVersionCatalogEntry> vs = new ArrayList<>(catalog.getOnlineVersions());\nvs.sort((a, b) -> com.alibaba.nacos.api.ai.utils.AgentVersionComparator.compare(b.getVersion(), a.getVersion()));\ncatalog.setOnlineVersions(vs);\n// verify strictly descending\nfor (int i = 1; i < vs.size(); i++) {\n    if (com.alibaba.nacos.api.ai.utils.AgentVersionComparator.compare(vs.get(i-1).getVersion(), vs.get(i).getVersion()) <= 0) {\n        throw new IllegalStateException(\"duplicate or unordered versions\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    AgentResourceExtSerializer.serialize(resourceExt);\n} catch (IllegalArgumentException e) {\n    if (\"Agent Version catalog must use descending Version order\".equals(e.getMessage())) {\n        sortCatalogDescending(catalog.getVersionCatalog());\n        AgentResourceExtSerializer.serialize(resourceExt); // retry once\n    } else throw e;\n}","preventionTips":["Always sort onlineVersions descending by AgentVersionComparator before publish.","De-duplicate versions before sorting.","When appending a new version, insert at the head, not the tail."],"tags":["ai-registry","agent","version-catalog","ordering"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}