{"record":{"id":"f4a9d2635a1cc53f","repo":"kubernetes/kops","slug":"failed-to-parse-kubernetes-version-s-w","errorCode":null,"errorMessage":"failed to parse kubernetes version (%s): %w","messagePattern":"failed to parse kubernetes version \\((.+?)\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apis/kops/util/versions.go","lineNumber":36,"sourceCode":"\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\n\t\"github.com/blang/semver/v4\"\n\t\"k8s.io/klog/v2\"\n)\n\nvar versionURLPattern = regexp.MustCompile(`/v1\\.([\\d]+)\\.`)\n\nfunc ParseKubernetesVersion(version string) (*semver.Version, error) {\n\tsv, err := semver.ParseTolerant(version)\n\tif err != nil {\n\t\tif submatch := versionURLPattern.FindStringSubmatch(version); len(submatch) >= 2 {\n\t\t\tminor, err := strconv.Atoi(submatch[1])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to parse kubernetes version (%s): %w\", version, err)\n\t\t\t}\n\t\t\tsv = semver.Version{Major: 1, Minor: uint64(minor)}\n\t\t} else {\n\t\t\tklog.Errorf(\"unable to parse Kubernetes version %q\", version)\n\t\t\treturn nil, fmt.Errorf(\"unable to parse kubernetes version %q\", version)\n\t\t}\n\t\tklog.V(1).Infof(\"Kubernetes version %q string matched to %v\", version, sv)\n\t}\n\n\treturn &sv, nil\n}\n\n// Deprecated: prefer using KubernetesVersion.IsGTE()\nfunc IsKubernetesGTE(version string, k8sVersion semver.Version) bool {\n\tparsedVersion, err := ParseKubernetesVersion(version)\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"Error parsing version %s: %v\", version, err))\n\t}","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/apis/kops/util/versions.go#L18-L54","documentation":"ParseKubernetesVersion wraps any failure converting the numeric minor captured from a version-URL-like string (e.g. .../v1.23/) into a semver.Version. It fires when semver.ParseTolerant fails but the string matches versionURLPattern, and the extracted minor component is not a valid integer. The error preserves the original input and the underlying strconv error via %w.","triggerScenarios":"Calling ParseKubernetesVersion (directly or via IsKubernetesGTE, IsGTE, RecommendedKubernetesVersion, FindRecommendedUpgrade, IsUpgradeRequired) with a string that fails strict/tolerant semver parsing but matches the version URL regex, where the regex's minor group is non-numeric (e.g. 'vX.abc' style URL).","commonSituations":"KubernetesVersion configured to a URL or image tag fragment instead of a plain version; cluster spec values copied from container image names; automated tooling substituting placeholders into the version field.","solutions":["Set the kubernetesVersion in the cluster spec to a plain semantic version like 1.28.4","Verify the string actually matches the expected version-URL format (numeric minor) before parsing","Use ParseKubernetesVersionInline/NormaliseKubernetesVersion or strip URL prefixes manually first","Log and inspect the offending version value; fix the upstream config source producing it"],"exampleFix":"// before\nv, err := ParseKubernetesVersion(\"https://storage.googleapis.com/k8s/release/vX.23\")\n// after\nv, err := ParseKubernetesVersion(\"1.23.0\")","handlingStrategy":"validation","validationCode":"re, _ := regexp.Compile(`/v1\\.[0-9]+/?$`)\nsv, err := semver.ParseTolerant(version)\nif err != nil && !re.MatchString(version) {\n    return fmt.Errorf(\"invalid kubernetes version %q\", version)\n}\n_, err = util.ParseKubernetesVersion(version)\nif err != nil { /* abort before calling kops APIs */ }","typeGuard":"func isParseableKubernetesVersion(v string) bool {\n    _, err := util.ParseKubernetesVersion(v)\n    return err == nil\n}","tryCatchPattern":"sv, err := util.ParseKubernetesVersion(raw)\nif err != nil {\n    klog.Warningf(\"skipping unparseable kubernetes version %q: %v\", raw, err)\n    return nil\n}","preventionTips":["Always store plain semver strings (e.g. 1.28.4) in kubernetesVersion fields","Validate version strings at config-load time, before calling kops APIs","Avoid copying container image tags or URLs into version fields","Add a CI check that parses all configured versions with ParseKubernetesVersion"],"tags":["kubernetes","version-parsing","semver","kops"],"backgroundTag":"version-string-parse-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}