crowdsecurity/crowdsec · error
cannot copy a folder onto itself
Error message
cannot copy a folder onto itself
What it means
checkPathNotContained walks up from the destination path; if the source absolute path is an ancestor of (or equal to) the destination, copying would move a folder into itself and corrupt/lose data, so it is rejected with this error. It is called by CopyDir before any copying happens.
Source
Thrown at pkg/hubtest/utils.go:62
}
// checkPathNotContained returns an error if 'subpath' is inside 'path'
func checkPathNotContained(path string, subpath string) error {
absPath, err := filepath.Abs(path)
if err != nil {
return err
}
absSubPath, err := filepath.Abs(subpath)
if err != nil {
return err
}
current := absSubPath
for {
if current == absPath {
return errors.New("cannot copy a folder onto itself")
}
up := filepath.Dir(current)
if current == up {
break
}
current = up
}
return nil
}
// CopyDir copies the content of a directory to another directory.
// It delegates the operation to os.CopyFS with an additional check to prevent infinite loops.
func CopyDir(src string, dest string) error {
if err := checkPathNotContained(src, dest); err != nil {
return errView on GitHub (pinned to 909b515798)
Solutions
- Choose a destination directory that is not inside the source directory
- Print both absolute paths and compare before running the copy
- If you intended an in-place move, use os.Rename instead of CopyDir
- Add a pre-check in the calling script using the same ancestor-walk logic
Example fix
// before: recursion attempt
CopyDir("/tmp/scenarios", "/tmp/scenarios/new")
// after: disjoint destination
CopyDir("/tmp/scenarios", "/tmp/copy-of-scenarios") Defensive patterns
Strategy: validation
Validate before calling
func isInside(dst, src string) bool {
absDst, _ := filepath.Abs(dst); absSrc, _ := filepath.Abs(src)
rel, err := filepath.Rel(absSrc, absDst)
return err == nil && rel != ".." && !strings.HasPrefix(rel, "..")+string(os.PathSeparator) && rel != "." && !strings.HasPrefix(rel, "..")
}
// call CopyDir only if !isInside(dst, src) Try / catch
if err := CopyDir(src, dst); err != nil {
if strings.Contains(err.Error(), "cannot copy a folder onto itself") {
return fmt.Errorf("destination %s is inside source %s; pick another target", dst, src)
}
return err
} Prevention
- Compare filepath.Abs of src and dst before copying
- Never use the source directory itself (or a shell-expanded variable) as destination
- Prefer os.Rename for in-place moves instead of CopyDir
- Log resolved absolute paths in scripts so containment mistakes are visible
When it happens
Trigger: Calling CopyDir(src, dst) where dst is inside src, or dst equals src — e.g. `cscli hubtest copy . ./sub` or copying /tmp/a into /tmp/a/b.
Common situations: Shell expansion or a config variable resolving to the same directory; accidentally passing a parent folder as the destination; scripts that concatenate paths without checking containment.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- unable to copy '%s' to '%s': %w
- unable to copy custom parser '%s' to '%s': %w
- too many levels of symbolic links
- can't read aws_config_dir %s got err %w
- unable to close %s : %s
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/5114f6e32ff822eb.
Report an issue: GitHub.