GoogleContainerTools/skaffold · error

unable to parse output: %q

Error message

unable to parse output: %q

What it means

Skaffold runs `helm version` and parses the output with VersionRegex (expects something like v3.x.x). If the regex finds no match, the output could not be interpreted as a Helm version string, so this error is returned with the raw output for inspection.

Source

Thrown at pkg/skaffold/helm/bin.go:93

	KubeContext() string
	Labels() map[string]string
	GlobalFlags() []string
	ManifestOverrides() map[string]string
}

// BinVer returns the version of the helm binary found in PATH.
func BinVer(ctx context.Context) (semver.Version, error) {
	// Helm v2 needed the `--client` to avoid connecting to Kubernetes.
	// Support for Helm v2 was dropped here.
	cmd := exec.CommandContext(ctx, "helm", "version")
	b, err := util.RunCmdOut(ctx, cmd)
	if err != nil {
		return semver.Version{}, fmt.Errorf("helm version command failed %q: %w", string(b), err)
	}
	raw := string(b)
	matches := VersionRegex.FindStringSubmatch(raw)
	if len(matches) == 0 {
		return semver.Version{}, fmt.Errorf("unable to parse output: %q", raw)
	}
	return semver.ParseTolerant(matches[1])
}

// PreparePostRenderer conditionally installs a post renderer plugin (starting from Helm v4) and returns
// an optional cleanup function in that case, plus in any case the needed command line arguments
func PreparePostRenderer(ctx context.Context, h Client, skaffoldBinary string, helmVersion semver.Version) (func(), []string, error) {
	if helmVersion.LT(Helm4PostRendererVersion) {
		return nil, []string{"--post-renderer", skaffoldBinary}, nil
	}

	// Helm v4 logic

	skaffoldBinaryAsYaml, err := yaml.Marshal(skaffoldBinary)
	if err != nil {
		return nil, nil, PluginErr("Failed to fill Skaffold executable into Helm plugin manifest", err)
	}

View on GitHub (pinned to a1189de023)

Solutions

  1. Inspect the printed raw output in the error to see what `helm version` returned
  2. Run `helm version` manually and confirm output contains `vX.Y.Z`
  3. Remove or rename wrapper/shim scripts shadowing the real helm binary (`type -a helm`)
  4. Install a standard Helm 3 release from official binaries

Example fix

// before: custom wrapper
helm() { echo "loading env"; /usr/local/bin/helm "$@"; }
// after: call real binary directly
alias helm=/usr/local/bin/helm  # ensure only helm prints version output
Defensive patterns

Strategy: validation

Validate before calling

out=$(helm version 2>&1); echo "$out" | grep -qE 'v[0-9]+\.[0-9]+\.[0-9]+' || { echo "unexpected helm version output: $out"; exit 1; }

Prevention

When it happens

Trigger: `helm version` succeeds but stdout does not match the expected `version.Version{...}` pattern: output wrapped by a shell wrapper, an alias or shim printing extra text, a very old/unusual helm build, or helm printing version only to a different stream.

Common situations: helm replaced by a wrapper script that banners extra lines; nightlies/custom builds with unexpected version strings; corporate shims (e.g. via asdf/mise) altering output; a non-helm binary named `helm` earlier on PATH.

Understand the failure class

Related errors


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