alibaba/nacos · error · IllegalArgumentException
Snapshot binding does not match selected Version: {selectedV
Error message
Snapshot binding does not match selected Version: {selectedVersion} What it means
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).
Source
Thrown at api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java:591
requireNonNull(item.getHealthy(), "runtime Endpoint healthy");
validateRuntimeEndpointState(item);
validateEpochMillis(item.getLastUpdatedTime(), "lastUpdatedTime");
}
private static void validateRuntimeVersionBinding(RuntimeVersionBinding binding,
AgentVersion selectedVersion, Set<String> bindingKeys) {
requireNonNull(binding, "runtime Version binding");
AgentVersion runtimeVersion = AgentVersion.parse(binding.getRuntimeVersion());
AgentVersionRange versionRange = AgentVersionRange.parse(binding.getVersionRange());
if (!versionRange.getValue().equals(binding.getVersionRange())) {
throw new IllegalArgumentException("Runtime Version range must be canonical");
}
if (!versionRange.contains(runtimeVersion)) {
throw new IllegalArgumentException(
"versionRange must contain runtimeVersion: " + runtimeVersion);
}
if (selectedVersion != null && !versionRange.contains(selectedVersion)) {
throw new IllegalArgumentException(
"Snapshot binding does not match selected Version: " + selectedVersion);
}
String bindingKey = runtimeVersion + "\u0000" + versionRange.getValue();
if (!bindingKeys.add(bindingKey)) {
throw new IllegalArgumentException("Duplicate Runtime Version binding");
}
}
private static void validateRuntimeEndpointState(RuntimeEndpointSnapshotItem item) {
RuntimeEndpointState expected;
if (!item.getEnabled()) {
expected = RuntimeEndpointState.DISABLED;
} else if (!item.getHealthy()) {
expected = RuntimeEndpointState.UNHEALTHY;
} else {
expected = RuntimeEndpointState.AVAILABLE;
}
if (item.getState() != expected) {View on GitHub (pinned to 9b989acdf1)
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())).
Example fix
// before
snapshot.setVersion("2.0.0");
binding.setVersionRange("[1.0.0,2.0.0)"); // excludes 2.0.0 -> rejected
// after
snapshot.setVersion("2.0.0");
binding.setVersionRange("[1.0.0,3.0.0)"); Defensive patterns
Strategy: validation
Validate before calling
String selected = snapshot.getVersion(); // may be null
if (selected != null) {
AgentValidationUtils.validateVersion(selected);
for (RuntimeEndpointSnapshotItem it : snapshot.getItems()) {
for (RuntimeVersionBinding b : it.getBindings()) {
// ensure AgentVersionRange.parse(b.getVersionRange()).contains(parse(selected))
// mirror with: range must include selected, e.g. exact or interval covering it.
}
}
} Type guard
static boolean snapshotVersionConsistent(RuntimeEndpointSnapshot snap) {
String v = snap.getVersion();
if (v == null) return true;
for (RuntimeEndpointSnapshotItem it : snap.getItems()) {
for (RuntimeVersionBinding b : it.getBindings()) {
// simplified: require range to textually include v or be unbounded above
if (!rangeContains(b.getVersionRange(), v)) return false;
}
}
return true;
} Try / catch
try {
AgentModelValidator.validateRuntimeEndpointSnapshot(snapshot);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Snapshot binding does not match selected Version")) {
// widen ranges or drop non-serving items or clear snapshot.version
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- versionRange must contain runtimeVersion: {runtimeVersion}
- Runtime Endpoint bindings must not be empty
- Runtime Version range must be canonical
- Duplicate Runtime Version binding
- Duplicate runtime Endpoint: {endpointKey}
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/23bed44ac2b3175a.
Report an issue: GitHub.