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

  1. 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.
  2. Ensure snapshot.version is the version you actually want resolved; if you want all endpoints regardless of version, leave snapshot.version null.
  3. Rebuild the snapshot from the set of endpoints known to serve snapshot.version rather than reusing an older snapshot.
  4. 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

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


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/23bed44ac2b3175a. Report an issue: GitHub.