ipfs/kubo · error
reading stash directory: %w
Error message
reading stash directory: %w
What it means
`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).
Source
Thrown at core/commands/update.go:694
slices.SortFunc(stashes, func(a, b stashEntry) int {
// Sort newest first: if a > b return -1.
if a.parsed.GreaterThan(b.parsed) {
return -1
}
if b.parsed.GreaterThan(a.parsed) {
return 1
}
return 0
})
return stashes, nil
}
// findLatestStash finds the most recently versioned stash file.
func findLatestStash(dir string) (path, ver string, err error) {
stashes, err := listStashes(dir)
if err != nil {
return "", "", fmt.Errorf("reading stash directory: %w", err)
}
if len(stashes) == 0 {
return "", "", fmt.Errorf("no stashed binaries found in %s", dir)
}
return stashes[0].path, stashes[0].ver, nil
}
// replaceBinary atomically replaces the binary at targetPath with data.
func replaceBinary(targetPath string, data []byte) error {
af, err := atomicfile.New(targetPath, 0o755)
if err != nil {
return err
}
if _, err := af.Write(data); err != nil {
_ = af.Abort()
return err
}View on GitHub (pinned to 329838acdf)
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.
Example fix
// before sudo ipfs update revert # stash dir owned by root: reading stash directory: permission denied // after sudo chown -R $USER: "$IPFS_PATH/stash" ipfs update revert
Defensive patterns
Strategy: validation
Validate before calling
stashDir := filepath.Join(repoPath, "stash")
if _, err := os.ReadDir(stashDir); err != nil {
// no stash directory: revert is impossible; skip or inform the user
}
if fi, err := os.Stat(stashDir); err == nil && fi.Mode()&0o400 == 0 {
// unreadable: fix ownership/permissions before invoking revert
} Type guard
func stashReadable(repoPath string) bool {
d := filepath.Join(repoPath, "stash")
fi, err := os.Stat(d)
return err == nil && fi.IsDir() && fi.Mode().Perm()&0o400 != 0
} Try / catch
path, ver, err := findLatestStash(dir)
if err != nil {
if strings.Contains(err.Error(), "reading stash directory") {
// distinguish missing/unreadable stash from empty stash
if _, statErr := os.Stat(dir); os.IsNotExist(statErr) {
return errors.New("never updated; nothing to revert to")
}
}
return fmt.Errorf("cannot revert: %w", err)
} Prevention
- 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.
When it happens
Trigger: `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.
Common situations: 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.
Related errors
- creating temp file: %w
- chmod temp file: %w
- serveHTTPApi: SetAPIAddr() failed: %w
- %s is not writeable by the current user
- cannot write to %s, incorrect permissions
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/bed72def474d46a8.
Report an issue: GitHub.