{"record":{"id":"deba49e8e689d864","repo":"anomalyco/sst","slug":"failed-to-move-extracted-package-w","errorCode":null,"errorMessage":"failed to move extracted package: %w","messagePattern":"failed to move extracted package: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/python/build.go","lineNumber":340,"sourceCode":"\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)\n\t}\n\n\tbaseName := dirName[:lastHyphen]\n\textractedDir := filepath.Join(outputDir, dirName)\n\ttargetDir := filepath.Join(outputDir, baseName)\n\n\t// Move extracted directory to target\n\tif err := moveExtractedPackage(extractedDir, targetDir, baseName); err != nil {\n\t\treturn fmt.Errorf(\"failed to move extracted package: %w\", err)\n\t}\n\n\t// Remove the original archive\n\tos.Remove(archiveFile)\n\n\treturn nil\n}\n\n// extractZip extracts a zip archive (used for .whl files) to the destination directory.\nfunc extractZip(archiveFile, destDir string) error {\n\tr, err := zip.OpenReader(archiveFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open zip: %w\", err)\n\t}\n\tdefer r.Close()\n\n\tfor _, f := range r.File {\n\t\t// Guard against zip slip","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/build.go#L322-L358","documentation":"After extracting an sdist, the code renames/moves the extracted `name-version` directory to `name` via `moveExtractedPackage`. This error wraps any failure of that move — permission issues, cross-device rename, or target directory conflicts.","triggerScenarios":"`processPackageArchive` extracted successfully but `moveExtractedPackage(extractedDir, targetDir, baseName)` failed, e.g. because outputDir and the extracted dir are on different filesystems, or a previous partial build left a conflicting `targetDir` directory.","commonSituations":"Output dir on an overlay/NFS mount where rename across devices fails; leftover directories from an interrupted previous build; file locks (Windows or editors) holding the directory open.","solutions":["Clean the build output directory and rebuild (`rm -rf .sst/build`)","Check that outputDir is on a local, writable filesystem","Verify no conflicting directory named after the package base already exists in outputDir","Re-run the deploy — transient locks from editors/AV scanners often clear"],"exampleFix":"// before: leftover requests/ dir from failed build causes move conflict\nrm -rf .sst/build && sst deploy","handlingStrategy":"try-catch","validationCode":"import { existsSync } from \"fs\";\nif (existsSync(`${outputDir}/${baseName}`)) throw new Error(`Conflicting dir ${baseName} in output — clean build dir`);","typeGuard":null,"tryCatchPattern":"try {\n  await buildPackage(...);\n} catch (e) {\n  if (String(e).includes(\"failed to move extracted package\")) {\n    console.error(\"Clean .sst/build (conflicting dir or cross-device move) and redeploy:\", e);\n  }\n  throw e;\n}","preventionTips":["Clean build output after failed/interrupted builds","Keep build output on a local filesystem, not NFS/overlay mounts","Close editors/tools that may lock build directories","Retry once after transient filesystem locks"],"tags":["python","filesystem","move","build"],"backgroundTag":"file-move-failed","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}