{"record":{"id":"f35667d603c57ffa","repo":"alibaba/nacos","slug":"latest-label-must-be-absent-when-no-online-version","errorCode":null,"errorMessage":"latest label must be absent when no online Version exists","messagePattern":"latest label must be absent when no online Version exists","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java","lineNumber":439,"sourceCode":"        for (AgentVersionCatalogEntry entry : onlineVersions) {\n            onlineVersionValues.add(entry.getVersion());\n        }\n        if (onlineVersionValues.contains(editingVersion)\n            || onlineVersionValues.contains(reviewingVersion)) {\n            throw new IllegalArgumentException(\n                \"editingVersion and reviewingVersion must not identify online Versions\");\n        }\n        for (Map.Entry<String, String> label : versionInfo.getLabels().entrySet()) {\n            if (label.getValue().equals(editingVersion)\n                || 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;","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java#L421-L457","documentation":"Thrown by validateVersionInfoCatalogConsistency when versionCatalog.latestVersion is null (i.e., no online Version exists) but versionInfo.labels contains a \"latest\" entry. The latest label is a computed pointer to the catalog's latest online Version; if there are no online Versions, the label must not exist. This is the null-catalog branch paired with error 490.","triggerScenarios":"Submitting a payload where onlineVersions is empty (so latestVersion is null) but labels still carries \"latest\" -> some version from a prior state.","commonSituations":"Taking the last online Version offline but forgetting to remove the \"latest\" label; building a new Agent and seeding labels with a default \"latest\" entry before any Version is online.","solutions":["Remove the \"latest\" key from versionInfo.labels when there are no online Versions.","When transitioning the last online Version to offline, clear both catalog.latestVersion and labels[\"latest\"] atomically.","On Agent creation with no online Versions, leave labels empty or exclude \"latest\"."],"exampleFix":"// before\ncatalog.setOnlineVersions(List.of()); versionInfo.getLabels().put(\"latest\", \"1.0.0\");\n// after\ncatalog.setOnlineVersions(List.of()); versionInfo.getLabels().remove(\"latest\");","handlingStrategy":"validation","validationCode":"static void syncLatestLabel(AgentVersionInfo info, AgentVersionCatalog catalog) {\n    if (catalog.getLatestVersion() == null) {\n        info.getLabels().remove(\"latest\");\n    }\n}","typeGuard":"static boolean latestLabelConsistentWhenEmpty(AgentVersionInfo info, AgentVersionCatalog catalog) {\n    return catalog.getLatestVersion() != null || info.getLabels().get(\"latest\") == null;\n}","tryCatchPattern":"try {\n    AgentModelValidator.validateAgent(agent);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"latest label must be absent\")) {\n        agent.getVersionInfo().getLabels().remove(\"latest\");\n    }\n}","preventionTips":["When the last online Version goes offline, clear labels[\"latest\"] in the same mutation.","On Agent creation with no online Versions, leave labels empty.","Treat latest as derived from the catalog, never as independent state."],"tags":["ai-agent","validation","version-info","labels","consistency","illegal-argument"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}