{"record":{"id":"6851425a6b753841","repo":"juicedata/juicefs","slug":"readdir-inode-d-s","errorCode":null,"errorMessage":"readdir inode %d: %s","messagePattern":"readdir inode (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/base.go","lineNumber":2371,"sourceCode":"\n\tif inode == TrashInode {\n\t\treturn []string{\"/.trash\"}\n\t}\n\n\toutside := \"path not shown because it's outside of the mounted root\"\n\tgetDirPath := func(ino Ino) (string, error) {\n\t\tvar names []string\n\t\tvar attr Attr\n\t\tfor ino != RootInode && ino != m.root {\n\t\t\tif st := m.en.doGetAttr(ctx, ino, &attr); st != 0 {\n\t\t\t\treturn \"\", fmt.Errorf(\"getattr inode %d: %s\", ino, st)\n\t\t\t}\n\t\t\tif attr.Typ != TypeDirectory {\n\t\t\t\treturn \"\", fmt.Errorf(\"inode %d is not a directory\", ino)\n\t\t\t}\n\t\t\tvar entries []*Entry\n\t\t\tif st := m.en.doReaddir(ctx, attr.Parent, 0, &entries, -1); st != 0 {\n\t\t\t\treturn \"\", fmt.Errorf(\"readdir inode %d: %s\", ino, st)\n\t\t\t}\n\t\t\tvar name string\n\t\t\tfor _, e := range entries {\n\t\t\t\tif e.Inode == ino {\n\t\t\t\t\tname = string(e.Name)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif attr.Parent == RootInode && ino == TrashInode {\n\t\t\t\tname = TrashName\n\t\t\t}\n\t\t\tif name == \"\" {\n\t\t\t\treturn \"\", fmt.Errorf(\"entry %d/%d not found\", attr.Parent, ino)\n\t\t\t}\n\t\t\tnames = append(names, name)\n\t\t\tino = attr.Parent\n\t\t}\n\t\tif m.root != RootInode && ino == RootInode {","sourceCodeStart":2353,"sourceCodeEnd":2389,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/base.go#L2353-L2389","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if st := meta.GetAttr(ctx, parent, &attr); st == 0 {\n    // parent alive; safe to walk\n}","typeGuard":null,"tryCatchPattern":"st, err := doLookup(ctx, ino)\nif err != nil {\n    if errors.Is(err, syscall.ENOENT) {\n        // re-resolve by path; handle is stale\n    }\n    return err\n}","preventionTips":["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"],"tags":["metadata","readdir","inode","filesystem"],"backgroundTag":"directory-not-found","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}