juicedata/juicefs · error

lookup inode for %s: %s

Error message

lookup inode for %s: %s

What it means

`juicefs rmr` removes a subtree directly through the mount's control file instead of walking the FUSE mount. For each argument path it needs the inode of the path's parent directory, obtained via utils.GetFileInode, so it can address the metadata engine. This error is returned when that inode lookup fails, aborting the whole rmr run.

Source

Thrown at cmd/rmr.go:105

		} else if runtime.GOOS == "windows" && !utils.IsWinAdminOrElevatedPrivilege() {
			logger.Fatalf("Removing files directly requires Administrator or elevated privilege on Windows")
		}
		flag = 1
	}
	progress := utils.NewProgress(false)
	spin := progress.AddCountSpinner("Removing entries")
	for i := 0; i < ctx.Args().Len(); i++ {
		path := ctx.Args().Get(i)
		p, err := filepath.Abs(path)
		if err != nil {
			logger.Errorf("abs of %q: %s", path, err)
			continue
		}
		d := filepath.Dir(p)
		name := filepath.Base(p)
		inode, err := utils.GetFileInode(d)
		if err != nil {
			return fmt.Errorf("lookup inode for %s: %s", d, err)
		}
		f, err := openController(d)
		if err != nil {
			logger.Errorf("Open control file for %q: %s", d, err)
			continue
		}
		wb := utils.NewBuffer(8 + 8 + 1 + uint32(len(name)) + 1 + 1)
		wb.Put32(meta.Rmr)
		wb.Put32(8 + 1 + uint32(len(name)) + 1 + 1)
		wb.Put64(inode)
		wb.Put8(uint8(len(name)))
		wb.Put([]byte(name))
		wb.Put8(flag)
		wb.Put8(uint8(numThreads))
		_, err = f.Write(wb.Bytes())
		if err != nil {
			logger.Fatalf("write message: %s", err)
		}

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Verify the path exists and its parent directory is inside a live JuiceFS mount (`ls <dir>` before rmr)
  2. Check the mount with `juicefs status` / `df` and remount if needed
  3. Run rmr as a user that can stat the parent directory (root may be needed for --skip-trash)
  4. Remove the path through the normal filesystem (rm -r) if inode addressing is not required

Example fix

// before
juicefs rmr /mnt/jfs/old-data/missing-subdir
// error: lookup inode for /mnt/jfs/old-data/missing-subdir: ...
// after
ls /mnt/jfs/old-data  # confirm parent exists on the mounted volume
juicefs rmr /mnt/jfs/old-data
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(filepath.Dir(path)); err != nil {
	log.Fatalf("parent dir not accessible: %v", err)
}

Type guard

null

Try / catch

if err := runRmr(path); err != nil {
	if strings.Contains(err.Error(), "lookup inode for") {
		// path is not on a live JuiceFS mount; fall back to os.RemoveAll
		os.RemoveAll(path)
	}
}

Prevention

When it happens

Trigger: Running `juicefs rmr <path>` where filepath.Dir(abs(path)) is not a file on a JuiceFS mount — e.g. the parent directory does not exist, the path is on a non-JuiceFS filesystem (GetFileInode cannot resolve an inode), or the mount is broken/unmounted so the statx/stat ioctl that reads the inode fails.

Common situations: Typo in the target path so the parent dir is missing; running rmr against a path outside any JuiceFS mount point; the volume was unmounted between listing and removal; permission problems prevent stat'ing the parent directory.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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