{"record":{"id":"5fecf70816d27e66","repo":"juicedata/juicefs","slug":"the-clone-dst-path-should-not-be-under-the-src-pat","errorCode":null,"errorMessage":"the clone DST path should not be under the SRC path","messagePattern":"the clone DST path should not be under the SRC path","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/clone.go","lineNumber":106,"sourceCode":"\t}\n\tdstAbsPath, err := filepath.Abs(dst)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"abs of %s: %s\", dst, err)\n\t}\n\n\tsrcMp, err := findMountpoint(srcAbsPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdstMp, err := findMountpoint(filepath.Dir(dstAbsPath))\n\tif err != nil {\n\t\treturn err\n\t}\n\tif srcMp != dstMp {\n\t\treturn fmt.Errorf(\"the clone DST path should be at the same mount point as the SRC path\")\n\t}\n\tif strings.HasPrefix(dstAbsPath, path.Clean(srcAbsPath)+\"/\") {\n\t\treturn fmt.Errorf(\"the clone DST path should not be under the SRC path\")\n\t}\n\n\tdstParent := filepath.Dir(dstAbsPath)\n\tdstName := filepath.Base(dstAbsPath)\n\tdstParentIno, err := utils.GetFileInode(dstParent)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"lookup inode for %s: %s\", dstParent, err)\n\t}\n\tvar cmode uint8\n\tumask := utils.GetUmask()\n\tif ctx.Bool(\"preserve\") || runtime.GOOS == \"windows\" {\n\t\tcmode |= meta.CLONE_MODE_PRESERVE_ATTR\n\t}\n\tthreads := ctx.Int(\"threads\")\n\tif threads < 1 {\n\t\tthreads = 1\n\t} else if threads > 255 {\n\t\tthreads = 255","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/cmd/clone.go#L88-L124","documentation":"Cloning a directory into a location under itself would create an infinite recursion (a directory containing a clone of itself). The command detects this by checking whether the absolute DST path is prefixed by the cleaned absolute SRC path plus '/', and rejects it.","triggerScenarios":"Running `juicefs clone /mnt/jfs/dir1 /mnt/jfs/dir1/copy` — DST lies inside the SRC directory tree. Also triggered when DST is a subdirectory deeper under SRC, e.g. cloning dir1 into dir1/sub/newname.","commonSituations":"User standing inside the source directory uses a relative DST that resolves under SRC (`cd /mnt/jfs/dir1 && juicefs clone .. copy` resolves differently, but `juicefs clone . ./copy` or `juicefs clone dir1 dir1/clone`); scripting that builds DST by joining SRC with a name.","solutions":["Choose a DST outside the SRC tree, e.g. a sibling: `juicefs clone /mnt/jfs/dir1 /mnt/jfs/dir1-copy`","Do not append the new name under SRC when scripting; join the SRC parent with the new name instead","If the paths only look nested via symlinks/../components, re-run with fully resolved absolute paths so the prefix check matches your intent"],"exampleFix":"// before\njuicefs clone /mnt/jfs/dir1 /mnt/jfs/dir1/clone  # error\n// after\njuicefs clone /mnt/jfs/dir1 /mnt/jfs/dir1-clone","handlingStrategy":"validation","validationCode":"cleanSrc := filepath.Clean(absSrc)\nif strings.HasPrefix(absDst, cleanSrc+string(os.PathSeparator)) {\n    return errors.New(\"DST must not be inside SRC\")\n}","typeGuard":null,"tryCatchPattern":"if err := runClone(src, dst); strings.Contains(err.Error(), \"under the SRC path\") {\n    dst = filepath.Join(filepath.Dir(src), filepath.Base(dst))\n    err = runClone(src, dst)\n}","preventionTips":["Never construct DST by joining names under SRC","Clone to a sibling path: filepath.Join(filepath.Dir(src), newName)","Resolve symlinks and .. before choosing DST","Add a prefix check in wrapper scripts before invoking clone"],"tags":["cli","filesystem","path-resolution","constraint"],"backgroundTag":"invalid-argument-value","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}