kubernetes/kops · error

unable to determine kubernetes version from %q: %w

Error message

unable to determine kubernetes version from %q: %w

What it means

After the general version parse, NewOptionsContext parses the same KubernetesVersion with kopsmodel.ParseKubernetesVersion to compute control-plane-specific version gates. Failure here wraps the underlying parse error and aborts options-context creation; it indicates the version string is not a valid semver per the stricter kops model parser.

Source

Thrown at pkg/model/components/context.go:64

	nodeKubernetesVersion         kopsmodel.KubernetesVersion
	controlPlaneKubernetesVersion kopsmodel.KubernetesVersion
}

func NewOptionsContext(cluster *kops.Cluster, assetBuilder *assets.AssetBuilder, maxKubeletSupportedVersion string) (*OptionsContext, error) {
	optionsContext := &OptionsContext{
		ClusterName:  cluster.ObjectMeta.Name,
		AssetBuilder: assetBuilder,
	}

	sv, err := util.ParseKubernetesVersion(cluster.Spec.KubernetesVersion)
	if err != nil {
		return nil, fmt.Errorf("unable to determine kubernetes version from %q", cluster.Spec.KubernetesVersion)
	}
	optionsContext.KubernetesVersion = *sv

	controlPlaneKubernetesVersion, err := kopsmodel.ParseKubernetesVersion(cluster.Spec.KubernetesVersion)
	if err != nil {
		return nil, fmt.Errorf("unable to determine kubernetes version from %q: %w", cluster.Spec.KubernetesVersion, err)
	}
	nodeKubernetesVersion := controlPlaneKubernetesVersion
	if maxKubeletSupportedVersion != "" {
		nodeKubernetesVersion, err = kopsmodel.ParseKubernetesVersion(maxKubeletSupportedVersion)
		if err != nil {
			return nil, fmt.Errorf("unable to determine kubernetes version from %q: %w", maxKubeletSupportedVersion, err)
		}
	}

	optionsContext.nodeKubernetesVersion = *nodeKubernetesVersion
	optionsContext.controlPlaneKubernetesVersion = *controlPlaneKubernetesVersion

	return optionsContext, nil
}

func (c *OptionsContext) NodeKubernetesVersion() kopsmodel.KubernetesVersion {
	return c.nodeKubernetesVersion
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Use full semver: major.minor.patch, e.g. v1.30.4
  2. Strip unsupported suffixes/whitespace from the version string
  3. Verify with `kops version`-compatible version formatting and re-run

Example fix

# before
kubernetesVersion: v1.30
# after
kubernetesVersion: v1.30.4
Defensive patterns

Strategy: validation

Validate before calling

if _, err := kopsmodel.ParseKubernetesVersion(cluster.Spec.KubernetesVersion); err != nil {
	return fmt.Errorf("kubernetesVersion %q is not full semver (use vMAJOR.MINOR.PATCH)", cluster.Spec.KubernetesVersion)
}

Type guard

func isFullSemver(v string) bool {
	_, err := kopsmodel.ParseKubernetesVersion(v)
	return err == nil && strings.Count(strings.TrimPrefix(v, "v"), ".") >= 2
}

Try / catch

if err := newOptionsContext(...); err != nil {
	if strings.Contains(err.Error(), "unable to determine kubernetes version") {
		// normalize to semver and retry
	}
	return err
}

Prevention

When it happens

Trigger: cluster.Spec.KubernetesVersion passes the lenient util parse but fails kopsmodel.ParseKubernetesVersion — e.g. missing patch version ('v1.30'), non-numeric pre-release tags, or leading/trailing whitespace.

Common situations: Using 'v1.30' style two-part versions; versions with suffixes like '-custom+build' unsupported by the parser; CI injecting branch names as versions.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/fb3b219ac9a93cc2. Report an issue: GitHub.