{"record":{"id":"afc83b64a0fd32a6","repo":"anomalyco/sst","slug":"failed-to-create-gzip-reader-w","errorCode":null,"errorMessage":"failed to create gzip reader: %w","messagePattern":"failed to create gzip reader: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/python/build.go","lineNumber":407,"sourceCode":"\t\t\treturn err\n\t\t}\n\t\tout.Close()\n\t\trc.Close()\n\t}\n\treturn nil\n}\n\n// extractTarGz extracts a .tar.gz archive to the destination directory.\nfunc extractTarGz(archiveFile, destDir string) error {\n\tf, err := os.Open(archiveFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open archive: %w\", err)\n\t}\n\tdefer f.Close()\n\n\tgz, err := gzip.NewReader(f)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create gzip reader: %w\", err)\n\t}\n\tdefer gz.Close()\n\n\ttr := tar.NewReader(gz)\n\tfor {\n\t\thdr, err := tr.Next()\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to read tar entry: %w\", err)\n\t\t}\n\n\t\ttarget := filepath.Join(destDir, hdr.Name)\n\t\t// Guard against tar slip\n\t\tif !strings.HasPrefix(filepath.Clean(target), filepath.Clean(destDir)+string(os.PathSeparator)) {\n\t\t\treturn fmt.Errorf(\"illegal file path in tar: %s\", hdr.Name)\n\t\t}","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/build.go#L389-L425","documentation":"After opening the file, extractTarGz calls gzip.NewReader, which reads the gzip magic header. If the file is not actually gzip-compressed (or is truncated/corrupt), the error is wrapped as \"failed to create gzip reader\". This catches cases where the downloaded file is an HTML error page, a plain wheel/zip, or a partially downloaded archive.","triggerScenarios":"The file at archiveFile is not valid gzip data: the download server returned an HTML 404/login page, the URL returned a .zip instead of a .tar.gz, the download was truncated by a network failure, or the file is a plain (uncompressed) .tar.","commonSituations":"Proxy or captive portal intercepts the download and serves an HTML error page; a package index mirror is broken; pip resolved to an sdist but the cached artifact is corrupt; an interrupted CI download left a partial file that was cached.","solutions":["Delete the corrupt archive and re-download it from the package index","Check the download URL/mirror is correct and serves real .tar.gz content (curl -I / file on the artifact)","Inspect the first bytes of the file (file archive.tar.gz or xxd) to confirm it is gzip data","Disable or fix the proxy/cache that may be serving an error page","Switch to a wheel (.whl) install path if the sdist download keeps failing"],"exampleFix":"// before: trusting a cached artifact\nerr := download(url, archiveFile)\nextractTarGz(archiveFile, destDir)\n\n// after: verify gzip magic bytes before extracting\ndata, _ := os.ReadFile(archiveFile)\nif len(data) < 2 || data[0] != 0x1f || data[1] != 0x8b {\n    os.Remove(archiveFile)\n    return fmt.Errorf(\"%s is not gzip, re-downloading\", archiveFile)\n}\nextractTarGz(archiveFile, destDir)","handlingStrategy":"validation","validationCode":"f, err := os.Open(archiveFile)\nif err != nil {\n    return err\n}\nmagic := make([]byte, 2)\nio.ReadFull(f, magic)\nf.Close()\nif magic[0] != 0x1f || magic[1] != 0x8b {\n    return fmt.Errorf(\"%s is not gzip data\", archiveFile)\n}","typeGuard":null,"tryCatchPattern":"if err := extractTarGz(archiveFile, destDir); err != nil {\n    if strings.Contains(err.Error(), \"failed to create gzip reader\") {\n        os.Remove(archiveFile) // drop corrupt artifact and re-download\n    }\n    return err\n}","preventionTips":["Verify gzip magic bytes before extracting","Validate downloaded artifacts against the index checksum","Avoid caching partial downloads (write to temp file, then atomic rename)","Check that proxies don't replace downloads with HTML error pages"],"tags":["gzip","archive","corrupt-file","python"],"backgroundTag":"corrupt-archive","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}