juicedata/juicefs · error
readdir inode %d: %s
Error message
readdir inode %d: %s
What it means
Wraps a nonzero status returned by doReaddir while walking up the ancestor chain to reconstruct an inode's path. It indicates the parent directory could not be listed (missing parent, permission/IO failure in the metadata engine), aborting path construction.
Source
Thrown at pkg/meta/base.go:2371
if inode == TrashInode {
return []string{"/.trash"}
}
outside := "path not shown because it's outside of the mounted root"
getDirPath := func(ino Ino) (string, error) {
var names []string
var attr Attr
for ino != RootInode && ino != m.root {
if st := m.en.doGetAttr(ctx, ino, &attr); st != 0 {
return "", fmt.Errorf("getattr inode %d: %s", ino, st)
}
if attr.Typ != TypeDirectory {
return "", fmt.Errorf("inode %d is not a directory", ino)
}
var entries []*Entry
if st := m.en.doReaddir(ctx, attr.Parent, 0, &entries, -1); st != 0 {
return "", fmt.Errorf("readdir inode %d: %s", ino, st)
}
var name string
for _, e := range entries {
if e.Inode == ino {
name = string(e.Name)
break
}
}
if attr.Parent == RootInode && ino == TrashInode {
name = TrashName
}
if name == "" {
return "", fmt.Errorf("entry %d/%d not found", attr.Parent, ino)
}
names = append(names, name)
ino = attr.Parent
}
if m.root != RootInode && ino == RootInode {View on GitHub (pinned to c9a67b23e8)
Solutions
- Re-resolve from the root: the ancestor chain is stale, so re-open the file via path instead of inode
- Check the wrapped status (%s) to identify the underlying engine error (e.g. ENOENT vs EPERM) and fix accordingly
- If ENOENT, refresh cached handles; if persistent, verify metadata backend integrity
Defensive patterns
Strategy: retry
Validate before calling
if st := meta.GetAttr(ctx, parent, &attr); st == 0 {
// parent alive; safe to walk
} Try / catch
st, err := doLookup(ctx, ino)
if err != nil {
if errors.Is(err, syscall.ENOENT) {
// re-resolve by path; handle is stale
}
return err
} Prevention
- Treat ENOENT during path walks as a stale-handle condition and re-resolve by path
- Avoid path reconstruction for inodes of concurrently deleted files
- Monitor metadata backend health (Redis/DB connectivity) to rule out engine failures
When it happens
Trigger: Path resolution walk calls m.en.doReaddir(ctx, attr.Parent, 0, &entries, -1) and receives a nonzero syscall status; e.g. the parent inode no longer exists, the engine returns an internal error, or access to the parent is denied.
Common situations: Reconstructing a path for an inode whose parent directory was concurrently deleted; truncated/corrupt metadata records for a parent inode; subdir-mounted volumes where parent links are inconsistent.
Related errors
- getattr inode %d: %s
- inode %d is not a directory
- lookup inode for %s: %s
- get inode of %s: %s
- Mkdir %s: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/6851425a6b753841.
Report an issue: GitHub.