GoogleContainerTools/skaffold · error

couldn't get kubectl minor version: %w

Error message

couldn't get kubectl minor version: %w

What it means

CompareVersionTo runs `kubectl version` via c.Version(ctx) and parses Major/Minor with strconv.Atoi to compare against a required version. When the Major string is not a plain integer, the parse error is wrapped — note the message misleadingly says 'minor version' even for the Major failure (a copy-paste bug in the error text).

Source

Thrown at pkg/skaffold/kubectl/version.go:71

// CheckVersion warns the user if their kubectl version is < 1.12.0
func (c *CLI) CheckVersion(ctx context.Context) error {
	comp, err := c.CompareVersionTo(ctx, 1, 12)
	if err != nil {
		return err
	}

	if comp < 0 {
		return errors.New("kubectl version 1.12.0 or greater is recommended for use with Skaffold")
	}
	return nil
}

func (c *CLI) CompareVersionTo(ctx context.Context, vMajor, vMinor int) (int, error) {
	v := c.Version(ctx)

	majorInt, err := strconv.Atoi(v.Major)
	if err != nil {
		return 0, fmt.Errorf("couldn't get kubectl minor version: %w", err)
	}

	// Some patched versions get a '+' suffix.
	minorInt, err := strconv.Atoi(strings.TrimRight(v.Minor, "+"))
	if err != nil {
		return 0, fmt.Errorf("couldn't get kubectl minor version: %w", err)
	}

	if majorInt > vMajor {
		return 1, nil
	}
	if majorInt == vMajor {
		if minorInt > vMinor {
			return 1, nil
		}
		if minorInt == vMinor {
			return 0, nil
		}

View on GitHub (pinned to a1189de023)

Solutions

  1. Run `kubectl version --client` and confirm it prints numeric major/minor values
  2. Install a standard upstream kubectl matching your cluster and put it first on PATH
  3. If using a forked kubectl whose version has suffixes, switch to upstream or update Skaffold

Example fix

// before: forked kubectl prints Major="v1" -> Atoi fails
// after: install upstream kubectl so Version() returns Major="1", Minor="27"
kubectl version --client=true -o json | jq -r '.clientVersion.major'
Defensive patterns

Strategy: validation

Validate before calling

out, err := exec.Command("kubectl", "version", "--client", "-o", "json").Output()
if err != nil {
    return fmt.Errorf("kubectl unavailable: %w", err)
}
var v struct{ ClientVersion struct{ Major, Minor string } }
if json.Unmarshal(out, &v) != nil || v.ClientVersion.Major == "" {
    return errors.New("kubectl returned non-standard version output; install upstream kubectl")
}

Type guard

func validKubectlVersion(major, minor string) bool {
    _, err1 := strconv.Atoi(major)
    _, err2 := strconv.Atoi(strings.TrimRight(minor, "+"))
    return err1 == nil && err2 == nil
}

Try / catch

cmp, err := cli.CompareVersionTo(ctx, 1, 20)
if err != nil {
    var perr *strconv.NumError
    if errors.As(err, &perr) {
        return fmt.Errorf("kubectl version output unparseable (%s); reinstall upstream kubectl: %w", perr.Num, err)
    }
    return err
}

Prevention

When it happens

Trigger: kubectl's reported Major version string is non-numeric: empty output (kubectl missing/failing), error/usage text instead of version info, or forked kubectl builds emitting suffixed versions like "1" with annotations the parser doesn't expect.

Common situations: kubectl not on PATH or failing to execute so Version returns empty fields; vendor/patched kubectl (GKE, Rancher, OpenShift forks) printing non-standard version strings; stale PATH entry pointing at a broken kubectl.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/4aeb0e3529aa04f0. Report an issue: GitHub.