{"record":{"id":"b5ca2f0990cf7ad8","repo":"helm/helm","slug":"unable-to-open-tarball-w","errorCode":null,"errorMessage":"unable to open tarball: %w","messagePattern":"unable to open tarball: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/action/lint.go","lineNumber":103,"sourceCode":"\t\t}\n\t}\n\treturn len(result.Errors) > 0\n}\n\nfunc lintChart(path string, vals map[string]any, namespace string, kubeVersion *common.KubeVersion, skipSchemaValidation bool) (support.Linter, error) {\n\tvar chartPath string\n\tlinter := support.Linter{}\n\n\tif strings.HasSuffix(path, \".tgz\") || strings.HasSuffix(path, \".tar.gz\") {\n\t\ttempDir, err := os.MkdirTemp(\"\", \"helm-lint\")\n\t\tif err != nil {\n\t\t\treturn linter, fmt.Errorf(\"unable to create temp dir to extract tarball: %w\", err)\n\t\t}\n\t\tdefer os.RemoveAll(tempDir)\n\n\t\tfile, err := os.Open(path)\n\t\tif err != nil {\n\t\t\treturn linter, fmt.Errorf(\"unable to open tarball: %w\", err)\n\t\t}\n\t\tdefer file.Close()\n\n\t\tif err = chartutil.Expand(tempDir, file); err != nil {\n\t\t\treturn linter, fmt.Errorf(\"unable to extract tarball: %w\", err)\n\t\t}\n\n\t\tfiles, err := os.ReadDir(tempDir)\n\t\tif err != nil {\n\t\t\treturn linter, fmt.Errorf(\"unable to read temporary output directory %s: %w\", tempDir, err)\n\t\t}\n\t\tif !files[0].IsDir() {\n\t\t\treturn linter, fmt.Errorf(\"unexpected file %s in temporary output directory %s\", files[0].Name(), tempDir)\n\t\t}\n\n\t\tchartPath = filepath.Join(tempDir, files[0].Name())\n\t} else {\n\t\tchartPath = path","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/helm/helm/blob/2a29f1770b62844b27197d2507377361d45ad7c0/pkg/action/lint.go#L85-L121","documentation":"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.","triggerScenarios":"`helm lint <file>.tgz` where os.Open fails - file deleted, wrong filename/working directory, or mode 000 / unreadable to the current user.","commonSituations":"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.","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`"],"exampleFix":"# before\nhelm lint ./mychart.tgz      # unable to open tarball: no such file\n\n# after\nhelm package ./chart -d . && helm lint ./mychart-0.1.0.tgz","handlingStrategy":"validation","validationCode":"if info, err := os.Stat(tgzPath); err != nil {\n    return fmt.Errorf(\"tarball %s not readable: %w\", tgzPath, err)\n} else if info.IsDir() {\n    return fmt.Errorf(\"tarball %s is a directory\", tgzPath)\n}","typeGuard":"func isTarballOpenErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"unable to open tarball\")\n}","tryCatchPattern":"if err := lintRun(tgzPath); err != nil {\n    if isTarballOpenErr(err) {\n        // fix path/permissions; the chart itself was never read\n    }\n    return err\n}","preventionTips":["test -f the artifact in CI before linting","Produce artifacts with `helm package` in the same step that consumes them"],"tags":["lint","tarball","filesystem","permissions"],"backgroundTag":null,"analyzedSha":"2a29f1770b62844b27197d2507377361d45ad7c0","analyzedAt":"2026-08-15T22:02:47.490Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}