kubernetes/kops · error
unable to parse kubernetes version %q
Error message
unable to parse kubernetes version %q
What it means
ParseKubernetesVersion returns this when the input is neither a valid (tolerant) semver string nor a version-URL-like string. It logs the unparseable value and returns a descriptive error quoting the original input. This is the terminal fallback for any unrecognized Kubernetes version format.
Source
Thrown at pkg/apis/kops/util/versions.go:41
"github.com/blang/semver/v4"
"k8s.io/klog/v2"
)
var versionURLPattern = regexp.MustCompile(`/v1\.([\d]+)\.`)
func ParseKubernetesVersion(version string) (*semver.Version, error) {
sv, err := semver.ParseTolerant(version)
if err != nil {
if submatch := versionURLPattern.FindStringSubmatch(version); len(submatch) >= 2 {
minor, err := strconv.Atoi(submatch[1])
if err != nil {
return nil, fmt.Errorf("failed to parse kubernetes version (%s): %w", version, err)
}
sv = semver.Version{Major: 1, Minor: uint64(minor)}
} else {
klog.Errorf("unable to parse Kubernetes version %q", version)
return nil, fmt.Errorf("unable to parse kubernetes version %q", version)
}
klog.V(1).Infof("Kubernetes version %q string matched to %v", version, sv)
}
return &sv, nil
}
// Deprecated: prefer using KubernetesVersion.IsGTE()
func IsKubernetesGTE(version string, k8sVersion semver.Version) bool {
parsedVersion, err := ParseKubernetesVersion(version)
if err != nil {
panic(fmt.Sprintf("Error parsing version %s: %v", version, err))
}
// Ignore Pre & Build fields
k8sVersion.Pre = nil
k8sVersion.Build = nil
View on GitHub (pinned to 4c8573c808)
Solutions
- Correct the kubernetesVersion value to a valid semver string (e.g. 1.28.4 or 1.28)
- Check for empty/missing configuration values feeding the version field
- If using a URL form, ensure it matches the kops version URL pattern with a numeric minor
- Run kops get cluster --name X -o yaml to inspect the stored kubernetesVersion and fix it via kops replace
Example fix
// before KubernetesVersion: "latest" // after KubernetesVersion: "1.28.4"
Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(v) == "" {
return errors.New("kubernetesVersion is empty")
}
if _, err := semver.ParseTolerant(v); err != nil {
return fmt.Errorf("kubernetesVersion %q is not a valid version", v)
} Type guard
func isWellFormedVersion(v string) bool {
_, err := semver.ParseTolerant(strings.TrimSpace(v))
return err == nil
} Try / catch
_, err := util.ParseKubernetesVersion(v)
if err != nil {
if strings.Contains(err.Error(), "unable to parse") {
return fmt.Errorf("fix kubernetesVersion %q: must look like 1.28.4", v)
}
return err
} Prevention
- Never leave kubernetesVersion empty or set it to channel labels like 'latest'
- Regex-check inputs (e.g. ^[0-9]+\.[0-9]+(\.[0-9]+)?([+|-].+)?$) before kops calls
- Trim and sanitize values sourced from env vars or files
- Pin versions against kops' supported-version list before applying
When it happens
Trigger: Passing any string to ParseKubernetesVersion (or callers IsKubernetesGTE, IsGTE, RecommendedKubernetesVersion, FindRecommendedUpgrade, IsUpgradeRequired) that does not parse as semver and does not match versionURLPattern — e.g. empty string, 'latest', '1.2x', or a URL without a minor digit.
Common situations: Empty or unset kubernetesVersion field; typos like '1..28'; using channel labels ('stable', 'latest') instead of versions; copying image repository names into the version field; upstream change to kops version-channel data.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse kubernetes version (%s): %w
- cannot parse kubernetes version %q
- error parsing version %q for package %q
- error parsing version %q: %v
- error parsing version %q: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/a5cc12e1f20b0568.
Report an issue: GitHub.