juicedata/juicefs · error
%s already exists
Error message
%s already exists
What it means
Before cloning, clone checks the destination with os.Stat and rejects it with "%s already exists" if anything (file, directory, or symlink) already occupies the destination path. Note that if the destination ends with a separator, the source's base name is appended first, so the effective destination may differ from the argument typed.
Source
Thrown at cmd/clone.go:85
srcPath := ctx.Args().Get(0)
srcAbsPath, err := filepath.Abs(srcPath)
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")View on GitHub (pinned to c9a67b23e8)
Solutions
- Remove or rename the existing destination before cloning.
- Choose a fresh destination path (or append a timestamp/unique suffix).
- If the destination is a directory, make sure it does not already contain a file named after the source's base name.
- In scripts, guard with a test -e check or use clone's behavior to skip when it exists.
Example fix
# before juicefs clone meta.sqlite3:0 /mnt/jfs/a /mnt/jfs/b # /mnt/jfs/b exists # after rm /mnt/jfs/b juicefs clone meta.sqlite3:0 /mnt/jfs/a /mnt/jfs/b
Defensive patterns
Strategy: validation
Validate before calling
dst := ctx.Args().Get(1)
if strings.HasSuffix(dst, "/") {
dst = filepath.Join(dst, filepath.Base(src))
}
if _, err := os.Stat(dst); err == nil {
return fmt.Errorf("destination %s exists; choose another", dst)
} Try / catch
if err := clone(ctx); err != nil && strings.HasSuffix(err.Error(), "already exists") {
// pick a unique destination and retry
newDst := fmt.Sprintf("%s.%d", ctx.Args().Get(1), time.Now().Unix())
log.Printf("retrying clone to %s", newDst)
} Prevention
- Generate unique destination names (timestamp/UUID suffix) in automation
- Clean up partial clones before retrying a failed run
- Remember trailing-slash destinations append the source base name — check for collisions there too
When it happens
Trigger: Running `juicefs clone <src> <dst>` where dst already exists; passing a trailing-slash destination directory that already contains a file with the source's base name; re-running a clone script without cleanup from a previous run.
Common situations: Retrying a failed clone without deleting the partial artifact; cloning into a directory that already holds the file; an automated pipeline re-executes the clone idempotently without a existence check.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- abs of %s: %s
- lookup inode for %s: %s
- stat %s: %s
- the clone DST path should be at the same mount point as the
- the clone DST path should not be under the SRC path
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/ac33c883316092bd.
Report an issue: GitHub.