AlistGo/alist · warning
cannot move a submodule
Error message
cannot move a submodule
What it means
During Move()'s handling of the /aa/bb/1 -> /aa/ case, the driver scans the source parent tree for the entry to move and finds its type is 'commit' — a git submodule pointer. Submodules cannot be relocated via the tree API because the pointer references another repository, so the move is rejected. drivers/github/driver.go:310.
Source
Thrown at drivers/github/driver.go:310
ancestorNewSha, err := d.newTree(ancestorOldSha, []interface{}{*delSrc, *dstNextTree})
if err != nil {
return err
}
rootSha, err = d.renewParentTrees(srcParentPath, ancestorOldSha, ancestorNewSha, "/")
if err != nil {
return err
}
} else if strings.HasPrefix(srcObj.GetPath(), dstDir.GetPath()) { // /aa/bb/1 -> /aa/
srcParentPath := stdpath.Dir(srcObj.GetPath())
srcParentTree, srcParentOldSha, err := d.getTreeDirectly(srcParentPath)
if err != nil {
return err
}
var src *TreeObjReq = nil
for _, t := range srcParentTree.Trees {
if t.Path == srcObj.GetName() {
if t.Type == "commit" {
return errors.New("cannot move a submodule")
}
src = &t.TreeObjReq
break
}
}
if src == nil {
return errs.ObjectNotFound
}
delSrc := *src
delSrc.Sha = nil
delSrcTree := make([]interface{}, 0, 2)
delSrcTree = append(delSrcTree, delSrc)
if len(srcParentTree.Trees) == 1 {
delSrcTree = append(delSrcTree, map[string]string{
"path": ".gitkeep",
"mode": "100644",
"type": "blob",View on GitHub (pinned to 843d9dc814)
Solutions
- Perform the reorganization with git (edit .gitmodules, git mv) and push, rather than through the driver.
- Leave submodule entries untouched in the mounted view.
- Hide submodule entries from listings if they cause confusion.
Defensive patterns
Strategy: type-guard
Validate before calling
// check tree entry type before moving
for _, t := range srcParentTree.Trees {
if t.Path == srcObj.GetName() && t.Type == "commit" {
return errors.New("submodule entries cannot be moved via the tree API")
}
} Type guard
func isCommitEntry(t TreeObj) bool { return t.Type == "commit" } Try / catch
if err := d.Move(ctx, src, dst); err != nil && strings.Contains(err.Error(), "submodule") {
// fall back to git-side reorganization
} Prevention
- Exclude submodule entries from move/copy UI actions.
- Do submodule reorganization with git mv + .gitmodules edits.
- Flag type=='commit' entries in listings as restricted.
When it happens
Trigger: Moving an object upward out of its parent where the located tree entry has Type == "commit" (submodule).
Common situations: Repos with vendored submodules where a user tries to reorganize directories through the file browser; submodule entries surfacing in listings and being treated like normal folders.
Related errors
- cannot rename a submodule
- cannot download a submodule
- cannot move parent dir to child
- cannot move in place
- committer email is required
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/2f843e316094a24c.
Report an issue: GitHub.