helm/helm · error

unable to open tarball: %w

Error message

unable to open tarball: %w

What it means

lintChart opens the tarball path with os.Open before extracting it to a temp dir; an open failure is wrapped as "unable to open tarball". It fires for local filesystem problems on the given .tgz path: the file does not exist or the process lacks read permission. The path was already chosen by suffix (.tgz/.tar.gz), so this is purely about reaching the file.

Source

Thrown at pkg/action/lint.go:103

		}
	}
	return len(result.Errors) > 0
}

func lintChart(path string, vals map[string]any, namespace string, kubeVersion *common.KubeVersion, skipSchemaValidation bool) (support.Linter, error) {
	var chartPath string
	linter := support.Linter{}

	if strings.HasSuffix(path, ".tgz") || strings.HasSuffix(path, ".tar.gz") {
		tempDir, err := os.MkdirTemp("", "helm-lint")
		if err != nil {
			return linter, fmt.Errorf("unable to create temp dir to extract tarball: %w", err)
		}
		defer os.RemoveAll(tempDir)

		file, err := os.Open(path)
		if err != nil {
			return linter, fmt.Errorf("unable to open tarball: %w", err)
		}
		defer file.Close()

		if err = chartutil.Expand(tempDir, file); err != nil {
			return linter, fmt.Errorf("unable to extract tarball: %w", err)
		}

		files, err := os.ReadDir(tempDir)
		if err != nil {
			return linter, fmt.Errorf("unable to read temporary output directory %s: %w", tempDir, err)
		}
		if !files[0].IsDir() {
			return linter, fmt.Errorf("unexpected file %s in temporary output directory %s", files[0].Name(), tempDir)
		}

		chartPath = filepath.Join(tempDir, files[0].Name())
	} else {
		chartPath = path

View on GitHub (pinned to 2a29f1770b)

Solutions

  1. Verify the file exists at that exact path: ls -l the tarball and compare with what you pass
  2. Fix permissions: chmod +r the tarball or run as a user that can read it
  3. In scripts, guard with a test -f check before calling helm lint
  4. Rebuild the package if the artifact is stale: `helm package ./chart`

Example fix

# before
helm lint ./mychart.tgz      # unable to open tarball: no such file

# after
helm package ./chart -d . && helm lint ./mychart-0.1.0.tgz
Defensive patterns

Strategy: validation

Validate before calling

if info, err := os.Stat(tgzPath); err != nil {
    return fmt.Errorf("tarball %s not readable: %w", tgzPath, err)
} else if info.IsDir() {
    return fmt.Errorf("tarball %s is a directory", tgzPath)
}

Type guard

func isTarballOpenErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "unable to open tarball")
}

Try / catch

if err := lintRun(tgzPath); err != nil {
    if isTarballOpenErr(err) {
        // fix path/permissions; the chart itself was never read
    }
    return err
}

Prevention

When it happens

Trigger: `helm lint <file>.tgz` where os.Open fails - file deleted, wrong filename/working directory, or mode 000 / unreadable to the current user.

Common situations: Linting a build artifact that a failed packaging step never produced; case-mismatched filenames; running helm as a different user without read access; CI cache miss leaving the tarball absent.

Related errors


AI-assisted analysis of helm/helm@2a29f1770b (2026-08-15). Data as JSON: /api/errors/b5ca2f0990cf7ad8. Report an issue: GitHub.