juicedata/juicefs · error
read trash
Error message
read trash
What it means
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.
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
Example fix
// before juicefs gc redis://remote:6379/1 // read trash: connection timed out // after: ensure reachability / retry redis-cli -h remote ping && juicefs gc redis://remote:6379/1
Defensive patterns
Strategy: retry
Validate before calling
if err := client.Ping(); err != nil {
// metadata engine down; trash scan will fail with 'read trash'
} Try / catch
if err := scanTrashFiles(ctx, scan); err != nil {
if isTransient(err) { // e.g. timeouts, connection reset
time.Sleep(backoff)
err = scanTrashFiles(ctx, scan)
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Metadata engine under load or restarted mid-scan; Redis/MySQL connection drops during long trash scans; network timeouts to a remote metadata server.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- readdir inode
- scan trash files
- statistic
- 2. ALL entries in the metadata engine
- changelog is not enabled, use `juicefs config
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/f74009211704965b.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/meta/base.go:3233
if st = m.emptyDir(ctx, e.Inode, true, &count, concurrent); st != 0 {
if st != syscall.ETIMEDOUT && st != syscall.EINTR {
logger.Warnf("empty subTrash %d/%s: %s", e.Inode, e.Name, st)
}
} else {
entries = entries[1:]
if st = m.en.doRmdir(ctx, TrashInode, string(e.Name), nil, nil); st != 0 {
logger.Warnf("rmdir subTrash %s: %s", e.Name, st)
}
}
}
return 0
}
func (m *baseMeta) scanTrashFiles(ctx Context, scan trashFileScan) error {
var st syscall.Errno
var entries []*Entry
if st = m.en.doReaddir(ctx, TrashInode, 1, &entries, -1); st != 0 {
return errors.Wrap(st, "read trash")
}
var subEntries []*Entry
for _, entry := range entries {
ts, err := time.Parse("2006-01-02-15", string(entry.Name))
if err != nil {
logger.Warnf("bad entry as a subTrash: %s", entry.Name)
continue
}
if m.getFormat().DirStats {
ds, st := m.GetDirStat(ctx, entry.Inode)
if st == 0 && ds != nil {
if _, err := scan(entry.Inode, uint64(ds.length), ts, ds.inodes); err != nil {
return errors.Wrap(err, "scan trash files")
}
continue
}
logger.Warnf("get dir stat %d: %s, fallback to readdir", entry.Inode, st)
}View on GitHub (pinned to c9a67b23e8)