AlistGo/alist · error
cannot copy parent dir to child
Error message
cannot copy parent dir to child
What it means
Copy() rejects copying a directory into its own subtree: strings.HasPrefix(dstDir.GetPath(), srcObj.GetPath()) detects that the destination is inside the source, which would recursively nest the copy inside itself. The guard mirrors the one in Move(). drivers/github/driver.go:529.
Source
Thrown at drivers/github/driver.go:529
ObjName: srcObj.GetName(),
ObjPath: srcObj.GetPath(),
ParentName: stdpath.Base(parentDir),
ParentPath: parentDir,
TargetName: newName,
TargetPath: stdpath.Join(parentDir, newName),
}, "rename")
if err != nil {
return err
}
return d.commit(message, rootSha)
}
func (d *Github) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
if !d.isOnBranch {
return errors.New("cannot write to non-branch reference")
}
if strings.HasPrefix(dstDir.GetPath(), srcObj.GetPath()) {
return errors.New("cannot copy parent dir to child")
}
d.commitMutex.Lock()
defer d.commitMutex.Unlock()
dstSha, newSha, _, _, err := d.copyWithoutRenewTree(srcObj, dstDir)
if err != nil {
return err
}
rootSha, err := d.renewParentTrees(dstDir.GetPath(), dstSha, newSha, "/")
if err != nil {
return err
}
message, err := getMessage(d.copyMsgTmpl, &MessageTemplateVars{
UserName: getUsername(ctx),
ObjName: srcObj.GetName(),
ObjPath: srcObj.GetPath(),
ParentName: stdpath.Base(stdpath.Dir(srcObj.GetPath())),
ParentPath: stdpath.Dir(srcObj.GetPath()),View on GitHub (pinned to 843d9dc814)
Solutions
- Choose a destination outside the source subtree (e.g. /a -> /backup/a).
- Fix caller logic to reject destinations prefixed by the source path.
- If duplicating in place was intended, copy to a sibling path first, then move.
Example fix
// before Copy(src=/docs, dst=/docs/copy) // rejected // after Copy(src=/docs, dst=/backup/docs) // valid
Defensive patterns
Strategy: validation
Validate before calling
if strings.HasPrefix(dstDir.GetPath()+"/", srcObj.GetPath()+"/") {
return errors.New("cannot copy a directory into itself")
} Type guard
func isCopyIntoSelf(src, dst model.Obj) bool {
return strings.HasPrefix(stdpath.Clean(dst.GetPath())+"/", stdpath.Clean(src.GetPath())+"/")
} Prevention
- Validate src/dst prefix relationships before Copy.
- Choose sibling or unrelated destinations for duplicates.
- Exclude the source subtree in destination pickers.
When it happens
Trigger: Copying /a to /a/b (destination path starts with the source path) through the UI or driver API.
Common situations: Drag-and-drop of a folder into its own child; automation computing dst as src + suffix without realizing the collision.
Related errors
- cannot move parent dir to child
- cannot move in place
- committer email is required
- committer name is required
- author email is required
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/6033111b6ac2de0f.
Report an issue: GitHub.