{"record":{"id":"f74009211704965b","repo":"juicedata/juicefs","slug":"read-trash","errorCode":null,"errorMessage":"read trash","messagePattern":"read trash","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/base.go","lineNumber":3233,"sourceCode":"\t\tif st = m.emptyDir(ctx, e.Inode, true, &count, concurrent); st != 0 {\n\t\t\tif st != syscall.ETIMEDOUT && st != syscall.EINTR {\n\t\t\t\tlogger.Warnf(\"empty subTrash %d/%s: %s\", e.Inode, e.Name, st)\n\t\t\t}\n\t\t} else {\n\t\t\tentries = entries[1:]\n\t\t\tif st = m.en.doRmdir(ctx, TrashInode, string(e.Name), nil, nil); st != 0 {\n\t\t\t\tlogger.Warnf(\"rmdir subTrash %s: %s\", e.Name, st)\n\t\t\t}\n\t\t}\n\t}\n\treturn 0\n}\n\nfunc (m *baseMeta) scanTrashFiles(ctx Context, scan trashFileScan) error {\n\tvar st syscall.Errno\n\tvar entries []*Entry\n\tif st = m.en.doReaddir(ctx, TrashInode, 1, &entries, -1); st != 0 {\n\t\treturn errors.Wrap(st, \"read trash\")\n\t}\n\tvar subEntries []*Entry\n\tfor _, entry := range entries {\n\t\tts, err := time.Parse(\"2006-01-02-15\", string(entry.Name))\n\t\tif err != nil {\n\t\t\tlogger.Warnf(\"bad entry as a subTrash: %s\", entry.Name)\n\t\t\tcontinue\n\t\t}\n\t\tif m.getFormat().DirStats {\n\t\t\tds, st := m.GetDirStat(ctx, entry.Inode)\n\t\t\tif st == 0 && ds != nil {\n\t\t\t\tif _, err := scan(entry.Inode, uint64(ds.length), ts, ds.inodes); err != nil {\n\t\t\t\t\treturn errors.Wrap(err, \"scan trash files\")\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlogger.Warnf(\"get dir stat %d: %s, fallback to readdir\", entry.Inode, st)\n\t\t}","sourceCodeStart":3215,"sourceCodeEnd":3251,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/base.go#L3215-L3251","documentation":"scanTrashFiles lists the trash directory via doReaddir on the TrashInode; a non-zero errno from the metadata engine is wrapped as 'read trash'. It means the trash area of the filesystem could not be enumerated in the metadata engine.","triggerScenarios":"Running trash-related maintenance (e.g. juicefs gc or dump with trash scanning) when the metadata engine errors on readdir of the trash inode — connection failure, timeout, or corrupt internal state.","commonSituations":"Metadata engine under load or restarted mid-scan; Redis/MySQL connection drops during long trash scans; network timeouts to a remote metadata server.","solutions":["Retry the command once the metadata engine is reachable (the wrapped errno tells which engine call failed)","Check metadata engine health/logs (Redis INFO, MySQL error log)","Reduce load or run maintenance during off-peak hours to avoid engine timeouts","If a specific engine error persists (e.g. corrupt data), restore metadata from backup"],"exampleFix":"// before\njuicefs gc redis://remote:6379/1   // read trash: connection timed out\n// after: ensure reachability / retry\nredis-cli -h remote ping && juicefs gc redis://remote:6379/1","handlingStrategy":"retry","validationCode":"if err := client.Ping(); err != nil {\n  // metadata engine down; trash scan will fail with 'read trash'\n}","typeGuard":null,"tryCatchPattern":"if err := scanTrashFiles(ctx, scan); err != nil {\n  if isTransient(err) { // e.g. timeouts, connection reset\n    time.Sleep(backoff)\n    err = scanTrashFiles(ctx, scan)\n  }\n}","preventionTips":["Run trash scans with generous engine timeouts and retries enabled","Schedule maintenance during low metadata-engine load","Keep metadata engine and client on the same network region"],"tags":["metadata","trash","readdir"],"backgroundTag":"file-read-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}