{"record":{"id":"52c10d41d50e2686","repo":"alibaba/nacos","slug":"versionrange-must-contain-runtimeversion-runtime","errorCode":null,"errorMessage":"versionRange must contain runtimeVersion: {runtimeVersion}","messagePattern":"versionRange must contain runtimeVersion: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java","lineNumber":587,"sourceCode":"            validateRuntimeVersionBinding(binding, selectedVersion, bindingKeys);\n        }\n        requireNonNull(item.getState(), \"runtime Endpoint state\");\n        requireNonNull(item.getEnabled(), \"runtime Endpoint enabled\");\n        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;","sourceCodeStart":569,"sourceCodeEnd":605,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java#L569-L605","documentation":"Thrown by validateRuntimeVersionBinding when the binding's runtimeVersion, parsed via AgentVersion.parse, is NOT contained in the binding's own versionRange (AgentVersionRange.contains). Each runtime endpoint binding must be self-consistent: the concrete runtimeVersion the endpoint is running must lie inside the version interval the binding advertises. A range that does not cover its own runtimeVersion is a contradictory declaration and is rejected before duplicate/selection checks.","triggerScenarios":"A RuntimeVersionBinding where AgentVersionRange.parse(versionRange).contains(AgentVersion.parse(runtimeVersion)) is false. E.g. runtimeVersion='2.5.0' with versionRange='[1.0.0,2.0.0)'. Reached during validateRuntimeVersionBinding in the runtime snapshot push path.","commonSituations":"Bumping the deployed runtimeVersion but forgetting to widen the advertised versionRange; mis-typing one of the two fields; copying a binding template and changing runtimeVersion without updating the range; using a pre-release runtimeVersion outside a range that only lists releases.","solutions":["Make versionRange cover runtimeVersion, e.g. for runtimeVersion '2.5.0' use versionRange '[1.0.0,3.0.0)' or '[2.5.0,3.0.0)'.","If the endpoint serves exactly one version, set versionRange to the canonical exact form '[<runtimeVersion>]'.","Re-derive versionRange from runtimeVersion programmatically rather than maintaining the two fields by hand.","Validate the pair with AgentVersionRange.parse(range).contains(AgentVersion.parse(runtime)) before submitting."],"exampleFix":"// before\nb.setRuntimeVersion(\"2.5.0\");\nb.setVersionRange(\"[1.0.0,2.0.0)\"); // 2.5.0 not in range -> rejected\n// after\nb.setRuntimeVersion(\"2.5.0\");\nb.setVersionRange(\"[2.0.0,3.0.0)\");","handlingStrategy":"validation","validationCode":"import com.alibaba.nacos.api.ai.utils.AgentValidationUtils;\nAgentValidationUtils.validateVersion(binding.getRuntimeVersion());\nAgentValidationUtils.validateVersionRange(binding.getVersionRange());\n// confirm containment by mirroring AgentVersionRange.contains semantics:\n// parse both and check runtimeVersion falls inside [lo,hi] bounds.","typeGuard":"// containment gate (mirrors AgentVersionRange.contains)\nstatic boolean rangeCoversRuntime(String range, String runtime) {\n    // best: call AgentValidationUtils.validate* then rely on server.\n    // Simple exact-form shortcut:\n    return range.equals(\"[\" + runtime + \"]\") || range.contains(runtime);\n}","tryCatchPattern":"try {\n    AgentModelValidator.validateRuntimeEndpointSnapshot(snapshot);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"versionRange must contain runtimeVersion\")) {\n        // widen versionRange to include runtimeVersion\n    } else throw e;\n}","preventionTips":["Keep runtimeVersion and versionRange derived from one source.","For single-version endpoints use versionRange = '[' + runtimeVersion + ']'.","Re-validate when bumping the deployed runtimeVersion."],"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"}