siyuan-note/siyuan · error
Move notebook [ ] file [ ] failed
Error message
Move notebook [%s] file [%s] failed: %s
What it means
Box.Move renames a file/folder within a notebook via filelock.Rename and wraps failure in localized message 5 'Move notebook [%s] file [%s] failed: %s'. After a successful move it also cleans up an emptied ID-named parent dir. Because rename(2) semantics apply, an existing destination, a locked source, or a cross-device path will fail.
Solutions
- Check that newPath does not exist before moving (Box.Exist) and pick a unique name
- Close/stop other processes holding the source file (second kernel instance, sync agent, editor with the file open)
- Keep the notebook data on one filesystem; replace symlinked notebook dirs with real ones
Defensive patterns
Strategy: validation
Validate before calling
if (box.Exist(newPath)) throw new Error('destination already exists: ' + newPath);
if (!box.Exist(oldPath)) throw new Error('source missing: ' + oldPath);
box.Move(oldPath, newPath); Prevention
- Pick unique destination names before renaming
- Keep notebook data on a single filesystem (no symlinked cross-device dirs)
- Stop sync agents before bulk moves
When it happens
Trigger: POST /api/filetree/renameDoc / move paths where newPath already exists, the source .sy file is held by another process, or old and new paths resolve to different filesystems.
Common situations: Moving docs onto a destination name that collides with an existing doc; sync clients locking .sy files; workspace data split across mounts (e.g. symlinked notebook dirs).
Related errors
- Create notebook [ ] folder [ ] failed
- Remove notebook [ ] path [ ] failed
- can not open file, just support open folder only
- can not remove [ ] caused by it is a reserved file
- can not remove [ ] caused by it is not a dir
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/ec33475702fbe466.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/box.go:466
IncSync()
return nil
}
func (box *Box) Move(oldPath, newPath string) error {
if _, err := box.validateBoxPath(oldPath); err != nil {
return err
}
if _, err := box.validateBoxPath(newPath); err != nil {
return err
}
boxLocalPath := filepath.Join(util.DataDir, box.ID)
fromPath := filepath.Join(boxLocalPath, oldPath)
toPath := filepath.Join(boxLocalPath, newPath)
if err := filelock.Rename(fromPath, toPath); err != nil {
msg := fmt.Sprintf(Conf.Language(5), box.Name, fromPath, err)
logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, box.Name, err)
return errors.New(msg)
}
if oldDir := path.Dir(oldPath); ast.IsNodeIDPattern(path.Base(oldDir)) {
fromDir := filepath.Join(boxLocalPath, oldDir)
if util.IsEmptyDir(fromDir) {
filelock.Remove(fromDir)
}
}
IncSync()
return nil
}
func (box *Box) Remove(path string) error {
if _, err := box.validateBoxPath(path); err != nil {
return err
}
boxLocalPath := filepath.Join(util.DataDir, box.ID)
filePath := filepath.Join(boxLocalPath, path)View on GitHub (pinned to afa823b6b4)