juicedata/juicefs · error

scan trash files

Error message

scan trash files

What it means

When scanning trash files, the per-entry scan callback returned an error; it is wrapped as 'scan trash files'. This propagates a failure from the caller-provided scan function (e.g. writing to a dump/backup target) during trash enumeration.

Source

Thrown at pkg/meta/base.go:3246

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)
		}
		subEntries = subEntries[:0]
		if st = m.en.doReaddir(ctx, entry.Inode, 1, &subEntries, -1); st != 0 {
			logger.Warnf("readdir subEntry %d: %s", entry.Inode, st)
			continue
		}
		for _, se := range subEntries {
			if se.Attr.Typ == TypeFile {
				clean, err := scan(se.Inode, se.Attr.Length, ts, 1)
				if err != nil {
					return errors.Wrap(err, "scan trash files")
				}
				if clean {
					// TODO: m.en.doUnlink(ctx, entry.Attr.Parent, string(entry.Name))

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Inspect the wrapped inner error for the callback's actual failure (disk full, broken pipe, upload error)
  2. Free space / fix permissions on the dump destination and retry
  3. If piping, ensure downstream consumers stay alive: juicefs dump ... | gzip > file.gz
  4. Re-run the dump — it is restartable since it reads metadata non-destructively

Example fix

// before
juicefs dump meta.db dump.json   // scan trash files: write ...: no space left on device
// after
df -h /backup && juicefs dump meta.db /backup/dump.json
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure dump destination is writable and has space before scanning
if fi, err := os.Stat(destDir); err != nil || !fi.IsDir() {
  // fix destination first
}

Try / catch

if err := scanTrashFiles(ctx, scan); err != nil {
  // errors.As/wrap reveals the callback's real failure (ENOSPC, broken pipe, upload error)
  return err
}

Prevention

When it happens

Trigger: Running juicefs dump/gc with trash scanning when the scan callback fails — typically the dump destination write fails, or the callback encounters an invalid entry it rejects.

Common situations: Dump target disk full or unwritable during 'juicefs dump'; S3/object store upload failure while backing up trash entries; interrupted pipes (juicefs dump | gzip where gzip dies).

Related errors


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