juicedata/juicefs · error
stat %s: %s
Error message
stat %s: %s
What it means
The `juicefs clone` command checks whether the destination path already exists by calling os.Stat. If Stat fails with an error that is NOT 'file does not exist' (e.g. permission denied on a parent directory, I/O error, or the path component is not a directory), the command cannot safely determine DST availability and wraps the raw error as "stat %s: %s".
Source
Thrown at cmd/clone.go:87
if err != nil {
return fmt.Errorf("abs of %s: %s", srcPath, err)
}
srcIno, err := utils.GetFileInode(srcPath)
if err != nil {
return fmt.Errorf("lookup inode for %s: %s", srcPath, err)
}
srcParentIno, err := utils.GetFileInode(filepath.Dir(srcAbsPath))
if err != nil {
return fmt.Errorf("lookup inode for %s: %s", filepath.Dir(srcAbsPath), err)
}
dst := ctx.Args().Get(1)
if strings.HasSuffix(dst, string(filepath.Separator)) {
dst = filepath.Join(dst, filepath.Base(srcPath))
}
if _, err := os.Stat(dst); err == nil {
return fmt.Errorf("%s already exists", dst)
} else if !os.IsNotExist(err) {
return fmt.Errorf("stat %s: %s", dst, err)
}
dstAbsPath, err := filepath.Abs(dst)
if err != nil {
return fmt.Errorf("abs of %s: %s", dst, err)
}
srcMp, err := findMountpoint(srcAbsPath)
if err != nil {
return err
}
dstMp, err := findMountpoint(filepath.Dir(dstAbsPath))
if err != nil {
return err
}
if srcMp != dstMp {
return fmt.Errorf("the clone DST path should be at the same mount point as the SRC path")
}
if strings.HasPrefix(dstAbsPath, path.Clean(srcAbsPath)+"/") {View on GitHub (pinned to c9a67b23e8)
Solutions
- Check permissions on every existing component of DST (ls -ld on each parent) and grant search (+x) permission for the running user
- Verify each prefix of DST is a directory: run `stat` on each path component and fix or remove the non-directory component
- Check for symlink loops (`namei -l DST`) and fix the symlink
- If the mount is broken, remount the JuiceFS volume (`juicefs mount ...`) and retry
- As a workaround, pick a DST path in a directory you can stat and that does not exist yet
Example fix
// before juicefs clone /mnt/jfs/a /mnt/jfs/otheruser/dir/x # EACCES // after sudo chmod o+x /mnt/jfs/otheruser/dir juicefs clone /mnt/jfs/a /mnt/jfs/otheruser/dir/x
Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(dst); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("cannot stat destination %s: %w", dst, err)
} Try / catch
err := sh.Run("juicefs", "clone", src, dst)
if strings.HasPrefix(err.Error(), "stat ") {
// inspect DST path components: permissions / ENOTDIR
} Prevention
- Stat-test the DST path in a preflight script before invoking clone
- Keep DST parents world-traversable or run clone as the directory owner
- Avoid DST paths containing regular-file components
- Check `namei -l DST` when paths involve multiple users or symlink chains
When it happens
Trigger: Running `juicefs clone SRC DST` where os.Stat(DST) fails with an error other than ENOENT — e.g. a parent directory of DST lacks execute/search permission (EACCES), a path component is not a directory (ENOTDIR), the filesystem is inaccessible, or a symlink loop exists.
Common situations: DST parent directory owned by another user without +x permission; DST contains a non-directory component (e.g. cloning to /mnt/jfs/file1/sub/file when file1 is a regular file); stale NFS/FUSE mount returning I/O errors; SELinux/AppArmor blocking stat on the target.
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
- the clone DST path should not be under the SRC path
- %s is not inside JuiceFS
- failed to lookup inode for %s: %s
- abs of %s: %s
- lookup inode for %s: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/33aa7e4f88f25671.
Report an issue: GitHub.