{"record":{"id":"ccaf42b536e3d023","repo":"anomalyco/sst","slug":"failed-to-extract-wheel-w","errorCode":null,"errorMessage":"failed to extract wheel: %w","messagePattern":"failed to extract wheel: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/python/build.go","lineNumber":313,"sourceCode":"\t\treturn fmt.Errorf(\"no package archive found for %s (tried patterns: %s-*.whl, %s-*.tar.gz, %s-*.whl, %s-*.tar.gz)\",\n\t\t\tpkg.Name, normalizedName, normalizedName, pkg.Name, pkg.Name)\n\t}\n\n\t// Process each archive file\n\tfor _, archiveFile := range files {\n\t\tif err := processPackageArchive(archiveFile, outputDir); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to process archive %s: %w\", archiveFile, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// processPackageArchive extracts and cleans up a single package archive\nfunc processPackageArchive(archiveFile, outputDir string) error {\n\tif strings.HasSuffix(archiveFile, \".whl\") {\n\t\tif err := extractZip(archiveFile, outputDir); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to extract wheel: %w\", err)\n\t\t}\n\n\t\tos.Remove(archiveFile)\n\n\t\treturn nil\n\t}\n\n\t// Extract tar.gz\n\tif err := extractTarGz(archiveFile, outputDir); err != nil {\n\t\treturn fmt.Errorf(\"failed to extract archive: %w\", err)\n\t}\n\n\t// Get the directory name without version number\n\tarchiveBaseName := filepath.Base(archiveFile)\n\tdirName := strings.TrimSuffix(archiveBaseName, \".tar.gz\")\n\tlastHyphen := strings.LastIndex(dirName, \"-\")\n\tif lastHyphen == -1 {\n\t\treturn fmt.Errorf(\"invalid archive name format: %s\", archiveBaseName)","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/build.go#L295-L331","documentation":"When a matched package archive is a `.whl` (zip) file, `processPackageArchive` extracts it via `extractZip`. This error wraps the failure of `zip.OpenReader` — the file could not be opened as a valid zip archive.","triggerScenarios":"Glob matched a `*.whl` file that is not a valid zip: truncated download, an HTML error page saved as .whl, or zero-byte file.","commonSituations":"Corporate proxy returning error pages that pip saved as wheels; disk-full during download; manually placed files ending in .whl in the build dir; interrupted previous build.","solutions":["Remove the offending .whl from the build output and rebuild so pip re-downloads it","Verify the wheel is valid: `python -m zipfile -t <file>.whl`","Check network/proxy settings if downloads were corrupted","Clean the whole build directory (`rm -rf .sst/build`) to avoid mixing stale artifacts"],"exampleFix":"// before: stale 0-byte requests-2.31.0-py3-none-any.whl in build dir\n// after\ncd .sst/build && rm -f *.whl && cd ../.. && sst deploy","handlingStrategy":"validation","validationCode":"import { statSync } from \"fs\";\nconst whl = statSync(archivePath);\nif (whl.size < 1024) throw new Error(`${archivePath} too small to be a valid wheel`);","typeGuard":null,"tryCatchPattern":"try {\n  await buildPackage(...);\n} catch (e) {\n  if (String(e).includes(\"failed to extract wheel\")) {\n    console.error(\"Invalid wheel — delete it and rebuild:\", e);\n  }\n  throw e;\n}","preventionTips":["Delete stale .whl files in build output after failed builds","Avoid caches that persist partially downloaded wheels","Check proxy settings that can corrupt binary downloads","Validate wheels with `unzip -t` when in doubt"],"tags":["python","wheel","zip","corrupt-file"],"backgroundTag":"archive-extraction-failed","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}