{"record":{"id":"3a629cefc9a6ad23","repo":"alibaba/nacos","slug":"version-catalog-label-does-not-match-versioninfo","errorCode":null,"errorMessage":"Version catalog label does not match versionInfo: {label}","messagePattern":"Version catalog label does not match versionInfo: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java","lineNumber":449,"sourceCode":"                || label.getValue().equals(reviewingVersion)) {\n                throw new IllegalArgumentException(\n                    \"Labels must not identify editing or reviewing Versions\");\n            }\n        }\n        String latestLabelVersion = versionInfo.getLabels().get(\"latest\");\n        if (catalog.getLatestVersion() == null) {\n            if (latestLabelVersion != null) {\n                throw new IllegalArgumentException(\n                    \"latest label must be absent when no online Version exists\");\n            }\n        } else if (!catalog.getLatestVersion().equals(latestLabelVersion)) {\n            throw new IllegalArgumentException(\n                \"latest label and versionCatalog.latestVersion must match\");\n        }\n        for (AgentVersionCatalogEntry entry : onlineVersions) {\n            for (String label : entry.getLabels()) {\n                if (!entry.getVersion().equals(versionInfo.getLabels().get(label))) {\n                    throw new IllegalArgumentException(\n                        \"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) {","sourceCodeStart":431,"sourceCodeEnd":467,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java#L431-L467","documentation":"Thrown by validateVersionInfoCatalogConsistency when an online catalog entry's label does not map back to that entry's Version in versionInfo.labels. Each non-latest label attached to an online Version in the catalog must, in versionInfo.labels, point to that same Version. This enforces bidirectional label consistency between the catalog and versionInfo.","triggerScenarios":"A catalog entry for Version 1.2.0 carries label \"stable\", but versionInfo.labels[\"stable\"] = \"1.1.0\" (or is absent). This mismatch means the catalog advertises a label that versionInfo resolves to a different Version.","commonSituations":"Reassigning a label in versionInfo during a canary shift without updating which catalog entry carries the label; merging two independently-edited halves of the model.","solutions":["For every label on every online catalog entry, ensure versionInfo.labels[label] == entry.version.","Treat labels as a single source of truth: derive catalog entry labels from versionInfo.labels (or vice versa) rather than editing both independently.","After any label move, run a reconciliation pass that re-derives catalog entry labels from versionInfo."],"exampleFix":"// before\ncatalogEntry120.setLabels(List.of(\"stable\")); versionInfo.getLabels().put(\"stable\", \"1.1.0\");\n// after\ncatalogEntry120.setLabels(List.of(\"stable\")); versionInfo.getLabels().put(\"stable\", \"1.2.0\");","handlingStrategy":"validation","validationCode":"static void checkCatalogLabelsMapBack(AgentVersionInfo info, AgentVersionCatalog catalog) {\n    for (var entry : catalog.getOnlineVersions()) {\n        for (String label : entry.getLabels()) {\n            String mapped = info.getLabels().get(label);\n            if (!entry.getVersion().equals(mapped)) {\n                throw new IllegalArgumentException(\n                    \"Version catalog label does not match versionInfo: \" + label);\n            }\n        }\n    }\n}","typeGuard":"static boolean catalogLabelsMapBack(AgentVersionInfo info, AgentVersionCatalog catalog) {\n    for (var entry : catalog.getOnlineVersions()) {\n        for (String label : entry.getLabels()) {\n            if (!entry.getVersion().equals(info.getLabels().get(label))) return false;\n        }\n    }\n    return true;\n}","tryCatchPattern":"try {\n    AgentModelValidator.validateAgent(agent);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Version catalog label does not match\")) {\n        // rebuild versionInfo.labels from catalog entry labels\n    }\n}","preventionTips":["Derive versionInfo.labels from the catalog (label -> entry.version) rather than editing both.","After any label move, run a reconciliation pass.","Treat labels as a single source of truth to avoid bidirectional drift."],"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"}