{"record":{"id":"bed72def474d46a8","repo":"ipfs/kubo","slug":"reading-stash-directory-w","errorCode":null,"errorMessage":"reading stash directory: %w","messagePattern":"reading stash directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/update.go","lineNumber":694,"sourceCode":"\tslices.SortFunc(stashes, func(a, b stashEntry) int {\n\t\t// Sort newest first: if a > b return -1.\n\t\tif a.parsed.GreaterThan(b.parsed) {\n\t\t\treturn -1\n\t\t}\n\t\tif b.parsed.GreaterThan(a.parsed) {\n\t\t\treturn 1\n\t\t}\n\t\treturn 0\n\t})\n\n\treturn stashes, nil\n}\n\n// findLatestStash finds the most recently versioned stash file.\nfunc findLatestStash(dir string) (path, ver string, err error) {\n\tstashes, err := listStashes(dir)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"reading stash directory: %w\", err)\n\t}\n\tif len(stashes) == 0 {\n\t\treturn \"\", \"\", fmt.Errorf(\"no stashed binaries found in %s\", dir)\n\t}\n\treturn stashes[0].path, stashes[0].ver, nil\n}\n\n// replaceBinary atomically replaces the binary at targetPath with data.\nfunc replaceBinary(targetPath string, data []byte) error {\n\taf, err := atomicfile.New(targetPath, 0o755)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := af.Write(data); err != nil {\n\t\t_ = af.Abort()\n\t\treturn err\n\t}","sourceCodeStart":676,"sourceCodeEnd":712,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/update.go#L676-L712","documentation":"`findLatestStash` wraps any error from `listStashes(dir)` — which does `os.ReadDir` on `<IPFS_PATH>/stash/` — with this message while trying to locate the most recent backup for revert/rollback. It means the stash directory itself could not be read, not that it is empty (that produces a separate error).","triggerScenarios":"`ipfs update revert`/`rollback` when the stash directory does not exist (never updated before), IPFS_PATH points at a wrong/nonexistent path, or the directory has permissions denying read access to the current user.","commonSituations":"Running revert without ever running an update; IPFS_HOME/IPFS_PATH env var pointing elsewhere than where the update ran; stash directory owned by root after a sudo-run update; directory deleted by cleanup tooling.","solutions":["Check the stash dir exists and is readable: `ls -la \"$IPFS_PATH/stash\"` (default `~/.ipfs/stash`).","Run revert as the user who owns IPFS_PATH (never sudo), or fix ownership: `chown -R $USER \"$IPFS_PATH/stash\"`.","Verify IPFS_PATH/IPFS_HOME point at the same repo used for the original update.","If no update was ever performed, revert is not possible — reinstall the desired kubo version directly instead."],"exampleFix":"// before\nsudo ipfs update revert   # stash dir owned by root: reading stash directory: permission denied\n\n// after\nsudo chown -R $USER: \"$IPFS_PATH/stash\"\nipfs update revert","handlingStrategy":"validation","validationCode":"stashDir := filepath.Join(repoPath, \"stash\")\nif _, err := os.ReadDir(stashDir); err != nil {\n\t// no stash directory: revert is impossible; skip or inform the user\n}\nif fi, err := os.Stat(stashDir); err == nil && fi.Mode()&0o400 == 0 {\n\t// unreadable: fix ownership/permissions before invoking revert\n}","typeGuard":"func stashReadable(repoPath string) bool {\n\td := filepath.Join(repoPath, \"stash\")\n\tfi, err := os.Stat(d)\n\treturn err == nil && fi.IsDir() && fi.Mode().Perm()&0o400 != 0\n}","tryCatchPattern":"path, ver, err := findLatestStash(dir)\nif err != nil {\n\tif strings.Contains(err.Error(), \"reading stash directory\") {\n\t\t// distinguish missing/unreadable stash from empty stash\n\t\tif _, statErr := os.Stat(dir); os.IsNotExist(statErr) {\n\t\t\treturn errors.New(\"never updated; nothing to revert to\")\n\t\t}\n\t}\n\treturn fmt.Errorf(\"cannot revert: %w\", err)\n}","preventionTips":["Never run `ipfs update` via sudo; keep IPFS_PATH owned by the daemon user.","Always revert using the same IPFS_PATH/IPFS_HOME used for the update.","Keep the stash directory between updates unless rollback is no longer needed.","Check `ls $IPFS_PATH/stash` after each update to confirm the backup exists."],"tags":["filesystem","permissions","update","rollback"],"backgroundTag":"stash-directory-missing","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}