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

  1. Remove or rename the existing destination before cloning.
  2. Choose a fresh destination path (or append a timestamp/unique suffix).
  3. If the destination is a directory, make sure it does not already contain a file named after the source's base name.
  4. 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

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


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