{"record":{"id":"fba887c1b91efd87","repo":"anomalyco/sst","slug":"failed-to-open-file-for-hashing-w","errorCode":null,"errorMessage":"failed to open file for hashing: %w","messagePattern":"failed to open file for hashing: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/python/python.go","lineNumber":458,"sourceCode":"\t\tif skip(relPath, info) {\n\t\t\tif info.IsDir() {\n\t\t\t\treturn filepath.SkipDir\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t\tdstPath := filepath.Join(dst, relPath)\n\t\tif info.IsDir() {\n\t\t\treturn os.MkdirAll(dstPath, info.Mode())\n\t\t}\n\t\treturn copyFile(p, dstPath)\n\t})\n}\n\n// hashFileContents computes a SHA256 hash of a file's contents.\nfunc hashFileContents(filePath string) (string, error) {\n\tfile, err := os.Open(filePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to open file for hashing: %w\", err)\n\t}\n\tdefer file.Close()\n\n\thasher := sha256.New()\n\tif _, err := io.Copy(hasher, file); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to hash file: %w\", err)\n\t}\n\n\treturn hex.EncodeToString(hasher.Sum(nil)), nil\n}\n\n// hasWorkspaceLayoutPatterns checks for package/src/package patterns that need flattening.\n// Scans up to one level below projectRoot to cover both single-package and monorepo layouts.\nfunc (r *PythonRuntime) hasWorkspaceLayoutPatterns(projectRoot string) bool {\n\tvar scan func(dir string, depth int) bool\n\tscan = func(dir string, depth int) bool {\n\t\tentries, err := os.ReadDir(dir)\n\t\tif err != nil {","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/python.go#L440-L476","documentation":"hashFileContents opens a file to compute its SHA256 and wraps os.Open failures with this message. The library throws it from copySyncedDependencies, which hashes files to detect changes for dev-mode sync. It means the file that the dependency list referenced could not be opened for reading at hash time.","triggerScenarios":"copySyncedDependencies calls hashFileContents(path) on a path that no longer exists (file deleted between dependency discovery and hashing) or is unreadable (permissions, symlink to nonexistent target, path too long).","commonSituations":"File removed by a concurrent build/clean while `sst dev` is syncing; stale cache pointing at an old dependency path; workspace package relocated or renamed; restrictive umask/permissions on files generated by another user (e.g. root in Docker).","solutions":["Verify the file exists at the hashed path (ls / stat) and recreate it if it was deleted","Restart `sst dev` so the dependency list and hashes are recomputed","Check file permissions/ownership of the dependency files","If files are frequently mid-write, ignore ENOENT for files that vanished during sync"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func fileExists(path string) bool {\n\tfi, err := os.Stat(path)\n\treturn err == nil && fi.Mode().IsRegular()\n}\n// before syncing: ensure every dependency path hashes-exists\n// if !fileExists(depPath) { recompute dependency list or skip }","typeGuard":null,"tryCatchPattern":"if err := sstDev(); err != nil {\n\tif strings.Contains(err.Error(), \"failed to open file for hashing\") {\n\t\t// file vanished or is unreadable: restart dev to rebuild dependency list\n\t}\n}","preventionTips":["Restart `sst dev` after moving/renaming workspace packages","Check permissions/ownership of dependency files (especially when mixing root and user runs)","Treat ENOENT on vanished files as skip rather than hard failure in custom tooling","Avoid running `cargo clean`-style cleanup tasks while dev sync is active"],"tags":["go","filesystem","hashing","dev-sync"],"backgroundTag":"file-open-failed","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}