{"record":{"id":"23bed44ac2b3175a","repo":"alibaba/nacos","slug":"snapshot-binding-does-not-match-selected-version","errorCode":null,"errorMessage":"Snapshot binding does not match selected Version: {selectedVersion}","messagePattern":"Snapshot binding does not match selected Version: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java","lineNumber":591,"sourceCode":"        requireNonNull(item.getHealthy(), \"runtime Endpoint healthy\");\n        validateRuntimeEndpointState(item);\n        validateEpochMillis(item.getLastUpdatedTime(), \"lastUpdatedTime\");\n    }\n    \n    private static void validateRuntimeVersionBinding(RuntimeVersionBinding binding,\n        AgentVersion selectedVersion, Set<String> bindingKeys) {\n        requireNonNull(binding, \"runtime Version binding\");\n        AgentVersion runtimeVersion = AgentVersion.parse(binding.getRuntimeVersion());\n        AgentVersionRange versionRange = AgentVersionRange.parse(binding.getVersionRange());\n        if (!versionRange.getValue().equals(binding.getVersionRange())) {\n            throw new IllegalArgumentException(\"Runtime Version range must be canonical\");\n        }\n        if (!versionRange.contains(runtimeVersion)) {\n            throw new IllegalArgumentException(\n                \"versionRange must contain runtimeVersion: \" + runtimeVersion);\n        }\n        if (selectedVersion != null && !versionRange.contains(selectedVersion)) {\n            throw new IllegalArgumentException(\n                \"Snapshot binding does not match selected Version: \" + selectedVersion);\n        }\n        String bindingKey = runtimeVersion + \"\\u0000\" + versionRange.getValue();\n        if (!bindingKeys.add(bindingKey)) {\n            throw new IllegalArgumentException(\"Duplicate Runtime Version binding\");\n        }\n    }\n    \n    private static void validateRuntimeEndpointState(RuntimeEndpointSnapshotItem item) {\n        RuntimeEndpointState expected;\n        if (!item.getEnabled()) {\n            expected = RuntimeEndpointState.DISABLED;\n        } else if (!item.getHealthy()) {\n            expected = RuntimeEndpointState.UNHEALTHY;\n        } else {\n            expected = RuntimeEndpointState.AVAILABLE;\n        }\n        if (item.getState() != expected) {","sourceCodeStart":573,"sourceCodeEnd":609,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java#L573-L609","documentation":"Thrown by validateRuntimeVersionBinding when the snapshot carries a top-level version (RuntimeEndpointSnapshot.version) — the 'selected version' the caller is resolving for — and a binding's versionRange does NOT contain that selected version. This guarantees every binding in a version-targeted snapshot is actually eligible to serve the requested Agent version. When snapshot.version is null this check is skipped entirely (selectedVersion is null).","triggerScenarios":"RuntimeEndpointSnapshot.version is set (non-null), so selectedVersion = AgentVersion.parse(snapshot.version); for some binding, AgentVersionRange.parse(binding.versionRange).contains(selectedVersion) is false. E.g. snapshot.version='2.0.0' but a binding's range is '[1.0.0,2.0.0)'. Reached in the runtime snapshot push path.","commonSituations":"Asking for snapshot resolution at version V but including a legacy endpoint whose range predates V; rolling out a new selected version before updating legacy endpoint bindings; mixing endpoints that serve different version eras in one version-scoped snapshot; stale cached bindings after a version cutover.","solutions":["Widen each affected binding's versionRange so it contains snapshot.version, or remove that endpoint item from the snapshot if it cannot serve the selected version.","Ensure snapshot.version is the version you actually want resolved; if you want all endpoints regardless of version, leave snapshot.version null.","Rebuild the snapshot from the set of endpoints known to serve snapshot.version rather than reusing an older snapshot.","Pre-check: for every binding, AgentVersionRange.parse(range).contains(AgentVersion.parse(snapshot.getVersion()))."],"exampleFix":"// before\nsnapshot.setVersion(\"2.0.0\");\nbinding.setVersionRange(\"[1.0.0,2.0.0)\"); // excludes 2.0.0 -> rejected\n// after\nsnapshot.setVersion(\"2.0.0\");\nbinding.setVersionRange(\"[1.0.0,3.0.0)\");","handlingStrategy":"validation","validationCode":"String selected = snapshot.getVersion(); // may be null\nif (selected != null) {\n    AgentValidationUtils.validateVersion(selected);\n    for (RuntimeEndpointSnapshotItem it : snapshot.getItems()) {\n        for (RuntimeVersionBinding b : it.getBindings()) {\n            // ensure AgentVersionRange.parse(b.getVersionRange()).contains(parse(selected))\n            // mirror with: range must include selected, e.g. exact or interval covering it.\n        }\n    }\n}","typeGuard":"static boolean snapshotVersionConsistent(RuntimeEndpointSnapshot snap) {\n    String v = snap.getVersion();\n    if (v == null) return true;\n    for (RuntimeEndpointSnapshotItem it : snap.getItems()) {\n        for (RuntimeVersionBinding b : it.getBindings()) {\n            // simplified: require range to textually include v or be unbounded above\n            if (!rangeContains(b.getVersionRange(), v)) return false;\n        }\n    }\n    return true;\n}","tryCatchPattern":"try {\n    AgentModelValidator.validateRuntimeEndpointSnapshot(snapshot);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Snapshot binding does not match selected Version\")) {\n        // widen ranges or drop non-serving items or clear snapshot.version\n    } else throw e;\n}","preventionTips":["If you want all endpoints regardless of version, leave snapshot.version null.","Rebuild the snapshot from endpoints known to serve the selected version.","Re-validate after a version cutover."],"tags":["ai-agent","validation","version-range","runtime-snapshot","bindings"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}