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 = pathView on GitHub (pinned to 2a29f1770b)
Solutions
- Verify the file exists at that exact path: ls -l the tarball and compare with what you pass
- Fix permissions: chmod +r the tarball or run as a user that can read it
- In scripts, guard with a test -f check before calling helm lint
- 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
- test -f the artifact in CI before linting
- Produce artifacts with `helm package` in the same step that consumes them
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
- should be a file, not a directory
- not a directory
- not a directory
- plugin package only supports directories, not tarballs
- error reading %s: %w
AI-assisted analysis of helm/helm@2a29f1770b (2026-08-15).
Data as JSON: /api/errors/b5ca2f0990cf7ad8.
Report an issue: GitHub.