{"record":{"id":"f73d2b08fd181ae8","repo":"anomalyco/sst","slug":"failed-to-walk-extracted-directory-w","errorCode":null,"errorMessage":"failed to walk extracted directory: %w","messagePattern":"failed to walk extracted directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/python/build.go","lineNumber":524,"sourceCode":"\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Skip directories\n\t\tif info.IsDir() {\n\t\t\treturn nil\n\t\t}\n\n\t\text := filepath.Ext(path)\n\t\tif ext == \".py\" || ext == \".pyi\" || info.Name() == \"py.typed\" {\n\t\t\tpythonFiles = append(pythonFiles, path)\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to walk extracted directory: %w\", err)\n\t}\n\n\t// Create output directory\n\tif err := os.MkdirAll(outputDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create output directory: %w\", err)\n\t}\n\n\tfor _, srcFile := range pythonFiles {\n\t\trelPath, _ := filepath.Rel(extractedDir, srcFile)\n\t\tdestFile := filepath.Join(outputDir, relPath)\n\n\t\tif err := copyFile(srcFile, destFile); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to copy %s to %s: %w\", srcFile, destFile, err)\n\t\t}\n\t}\n\n\t// Clean up the extracted directory\n\tos.RemoveAll(extractedDir)","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/build.go#L506-L542","documentation":"flattenPackageToRoot walks the extracted directory with filepath.WalkDir to move package contents up one level (flattening versioned dirs like pkg-1.0.0/ into the package root). If the walk callback returns an error, it is wrapped as \"failed to walk extracted directory\". This indicates unreadable directories/files in the freshly extracted archive or a filesystem error during traversal.","triggerScenarios":"filepath.WalkDir fails because an extracted entry is unreadable (permissions from the tar preserved restrictive modes), a symlink points outside the archive, or an I/O error occurs while listing directories.","commonSituations":"Archives containing files with mode 000 or ownership of another user; macOS-style archives with resource-fork entries that break traversal; symlink-heavy packages; extraction to a failing/full disk.","solutions":["Check permissions on the extracted directory and chmod readable/executable as needed (find extractedDir -type d -exec chmod u+rx {} +)","Re-extract with modes normalized so restrictive tar modes don't propagate","Inspect for symlinks or odd entries with tar -tzvf and remove/repackage them if you own the archive","Verify disk health and free space","As a workaround, disable flattening by using a standard (non-flattened) package layout"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"err := filepath.WalkDir(extractedDir, func(p string, d fs.DirEntry, err error) error {\n    if err != nil {\n        return err\n    }\n    info, err := d.Info()\n    if err != nil {\n        return err\n    }\n    if info.Mode()&0400 == 0 {\n        return fmt.Errorf(\"unreadable entry: %s\", p)\n    }\n    return nil\n})\nif err != nil {\n    return fmt.Errorf(\"extracted dir not traversable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := processPackageArchive(...); err != nil {\n    if strings.Contains(err.Error(), \"failed to walk extracted directory\") {\n        // fix permissions on extractedDir and retry once\n        exec.Command(\"chmod\", \"-R\", \"u+rX\", extractedDir).Run()\n        return retry()\n    }\n    return err\n}","preventionTips":["Normalize file modes after extraction so restrictive tar modes don't block traversal","Run the build as the same user that owns the extracted files","Avoid archives containing symlinks outside the package root","Check disk health/space if walk errors persist"],"tags":["filesystem","walk","permissions","python"],"backgroundTag":"permission-denied","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}