{"record":{"id":"26be1575d15f681f","repo":"alibaba/nacos","slug":"online-version-label-is-missing-from-versioncatalo","errorCode":null,"errorMessage":"Online Version label is missing from versionCatalog: {label.key}","messagePattern":"Online Version label is missing from versionCatalog: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java","lineNumber":468,"sourceCode":"                        \"Version catalog label does not match versionInfo: \" + label);\n                }\n            }\n        }\n        for (Map.Entry<String, String> label : versionInfo.getLabels().entrySet()) {\n            if (\"latest\".equals(label.getKey())\n                || !onlineVersionValues.contains(label.getValue())) {\n                continue;\n            }\n            boolean presentInCatalog = false;\n            for (AgentVersionCatalogEntry entry : onlineVersions) {\n                if (entry.getVersion().equals(label.getValue())\n                    && entry.getLabels().contains(label.getKey())) {\n                    presentInCatalog = true;\n                    break;\n                }\n            }\n            if (!presentInCatalog) {\n                throw new IllegalArgumentException(\n                    \"Online Version label is missing from versionCatalog: \" + label.getKey());\n            }\n        }\n    }\n    \n    private static void validateCatalogLabels(List<String> labels, Set<String> allLabels) {\n        requireNonNull(labels, \"versionCatalog.labels\");\n        Set<String> entryLabels = new HashSet<String>();\n        for (String label : labels) {\n            AgentValidationUtils.validateNonLatestLabel(label);\n            if (!entryLabels.add(label) || !allLabels.add(label)) {\n                throw new IllegalArgumentException(\"Duplicate Version label: \" + label);\n            }\n        }\n    }\n    \n    private static void validateProtocols(List<String> protocols, String fieldName) {\n        requireNonNull(protocols, fieldName);","sourceCodeStart":450,"sourceCodeEnd":486,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java#L450-L486","documentation":"Thrown by validateVersionInfoCatalogConsistency for the reverse direction of error 491: when versionInfo.labels contains a (non-latest) entry whose value is an online Version, but the catalog entry for that Version does not list that label key. The label must exist on both sides; an online Version referenced by a label must advertise that label in the catalog.","triggerScenarios":"versionInfo.labels[\"canary\"] = \"1.4.0\" and 1.4.0 is in onlineVersions, but the catalog entry for 1.4.0 has no \"canary\" in its labels list. The versionInfo promises a label the catalog does not surface.","commonSituations":"Adding a label in versionInfo to route traffic but forgetting to attach it to the catalog entry; importing versionInfo from one system and the catalog from another.","solutions":["For each non-latest versionInfo label whose value is an online Version, add that label key to the matching catalog entry's labels list.","Generate catalog entry labels directly from versionInfo.labels (invert the map) so the two cannot drift.","Run a bidirectional reconciliation: every label-value pair must appear on both the versionInfo side and the catalog entry side."],"exampleFix":"// before\nversionInfo.getLabels().put(\"canary\", \"1.4.0\"); entry140.setLabels(List.of());\n// after\nversionInfo.getLabels().put(\"canary\", \"1.4.0\"); entry140.setLabels(List.of(\"canary\"));","handlingStrategy":"validation","validationCode":"static void checkVersionInfoLabelsAdvertised(AgentVersionInfo info, AgentVersionCatalog catalog) {\n    Map<String, AgentVersionCatalogEntry> byVersion = new HashMap<>();\n    for (var en : catalog.getOnlineVersions()) byVersion.put(en.getVersion(), en);\n    for (var label : info.getLabels().entrySet()) {\n        if (\"latest\".equals(label.getKey())) continue;\n        AgentVersionCatalogEntry en = byVersion.get(label.getValue());\n        if (en != null && !en.getLabels().contains(label.getKey())) {\n            throw new IllegalArgumentException(\n                \"Online Version label is missing from versionCatalog: \" + label.getKey());\n        }\n    }\n}","typeGuard":"static boolean versionInfoLabelsAdvertised(AgentVersionInfo info, AgentVersionCatalog catalog) {\n    Map<String, AgentVersionCatalogEntry> byVersion = new HashMap<>();\n    for (var en : catalog.getOnlineVersions()) byVersion.put(en.getVersion(), en);\n    return info.getLabels().entrySet().stream().allMatch(l ->\n        \"latest\".equals(l.getKey())\n        || byVersion.get(l.getValue()) == null\n        || byVersion.get(l.getValue()).getLabels().contains(l.getKey()));\n}","tryCatchPattern":"try {\n    AgentModelValidator.validateAgent(agent);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Online Version label is missing\")) {\n        // add missing label keys to the matching catalog entries\n    }\n}","preventionTips":["Generate catalog entry labels by inverting versionInfo.labels so the two cannot drift.","Run a bidirectional reconciliation before submission.","Never edit versionInfo.labels and catalog entry labels through independent code paths."],"tags":["ai-agent","validation","version-info","labels","catalog","consistency","illegal-argument"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}