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

  1. Re-resolve from the root: the ancestor chain is stale, so re-open the file via path instead of inode
  2. Check the wrapped status (%s) to identify the underlying engine error (e.g. ENOENT vs EPERM) and fix accordingly
  3. 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

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


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/6851425a6b753841. Report an issue: GitHub.