{"record":{"id":"999c3f8dda95f2e6","repo":"anomalyco/sst","slug":"failed-to-scan-artifact-files-v","errorCode":null,"errorMessage":"failed to scan artifact files: %v","messagePattern":"failed to scan artifact files: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/python/python.go","lineNumber":309,"sourceCode":"\tif _, err := os.Stat(destDir); err == nil {\n\t\terr = filepath.Walk(destDir, func(path string, info os.FileInfo, err error) error {\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\trelPath, err := filepath.Rel(destDir, path)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif !info.IsDir() && strings.HasSuffix(path, \".py\") {\n\t\t\t\tartifactFiles[relPath] = info\n\t\t\t}\n\n\t\t\treturn nil\n\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to scan artifact files: %v\", err)\n\t\t}\n\t}\n\n\t// Delete files in artifacts that no longer exist in source\n\tfor relPath := range artifactFiles {\n\t\tif _, exists := sourceFiles[relPath]; !exists {\n\t\t\tartifactPath := filepath.Join(destDir, relPath)\n\t\t\tif err := os.Remove(artifactPath); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to delete %s: %v\", artifactPath, err)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Copy/update changed files\n\tfor relPath, sourceInfo := range sourceFiles {\n\t\tsourcePath := filepath.Join(srcDir, relPath)\n\t\tartifactPath := filepath.Join(destDir, relPath)\n","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/python.go#L291-L327","documentation":"Raised in syncPythonFiles (pkg/runtime/python/python.go:309) when filepath.Walk over the artifact output directory (input.Build.Out) fails while collecting existing .py artifact files. Only runs when the dest dir exists. Indicates the artifact directory became unreadable or changed (deleted files, permission loss) during the sync.","triggerScenarios":"Artifact dir (.sst artifacts for the function) with read-restricted subdirectories; files deleted mid-walk by a concurrent build; a corrupt or partially-written artifact directory from an interrupted deploy.","commonSituations":"Two sst processes sharing one project writing artifacts simultaneously; artifacts directory synced/restored with wrong permissions; interrupted `sst deploy` leaving broken dirs in legacy workspace-layout Python projects.","solutions":["Check the wrapped error path and fix permissions: chmod -R u+rX <path>","Stop other sst processes, delete the function's artifact directory, and let `sst dev`/`sst deploy` rebuild it fresh","If recurring in CI, run builds in isolated workspaces so concurrent runs don't share .sst artifacts"],"exampleFix":"// before\nsst dev -> failed to scan artifact files: open .sst/artifacts/... : permission denied\n// after\nrm -rf .sst/artifacts/<function-dir>\nsst dev","handlingStrategy":"validation","validationCode":"// check artifact dir is usable before sync\nif info, err := os.Stat(artifactDir); err == nil {\n    if !info.IsDir() { return fmt.Errorf(\"artifact path is not a directory: %s\", artifactDir) }\n    if f, err := os.Open(artifactDir); err != nil { return fmt.Errorf(\"artifact dir unreadable: %v\", err) } else { f.Close() }\n}","typeGuard":null,"tryCatchPattern":"if err := syncPythonFiles(src, dst); err != nil {\n    if strings.Contains(err.Error(), \"failed to scan artifact files\") {\n        os.RemoveAll(dst) // nuke corrupt artifacts, rebuild clean\n        return syncPythonFiles(src, dst)\n    }\n    return err\n}","preventionTips":["Don't run two sst processes against the same project directory","After interrupted deploys, remove the affected artifact dir and rebuild","Ensure container/CI builds chown .sst back to your user","Keep the artifacts dir on a local, writable filesystem"],"tags":["filesystem","permissions","artifacts","sync","python"],"backgroundTag":"permission-denied","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}