siyuan-note/siyuan · error

Move notebook [%s] file [%s] failed: %s

Error message

Move notebook [%s] file [%s] failed: %s

What it means

Thrown by the internal moveDocsByPath function during a cross-box (isSameBox=false) move, when renaming the source document's sub-document folder (filelock.Rename) from the source notebook's data directory to the destination's fails. Conf.Language(5) = 'Move notebook [%s] file [%s] failed: %s', formatted with the source box name, source path, and the OS-level rename error. This is the sub-doc folder move (not the .sy file itself), occurring when the source document has child documents stored in a folder.

Source

Thrown at kernel/model/file.go:1872

	needMoveSubDocs := fromBox.Exist(fromFolder)
	if needMoveSubDocs {
		// 移动子文档文件夹

		newFolder := path.Join(toFolder, tree.ID)
		if isSameBox {
			if err = fromBox.Move(fromFolder, newFolder); err != nil {
				return
			}
		} else {
			absFromPath := filepath.Join(util.DataDir, fromBox.ID, fromFolder)
			absToPath := filepath.Join(util.DataDir, toBox.ID, newFolder)
			if filelock.IsExist(absToPath) {
				filelock.Remove(absToPath)
			}
			if err = filelock.Rename(absFromPath, absToPath); err != nil {
				msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
				logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBox.ID, err)
				err = errors.New(msg)
				return
			}
		}
	}

	newPath = path.Join(toFolder, tree.ID+".sy")

	if isSameBox {
		if err = fromBox.Move(fromPath, newPath); err != nil {
			return
		}

		tree, err = filesys.LoadTree(fromBox.ID, newPath, luteEngine)
		if err != nil {
			return
		}

		moveTree(tree)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Check kernel logs for the specific OS error appended to the message (the %s at the end of Language(5)).
  2. If moving across filesystems, ensure both notebook data directories are on the same volume, or use copy-then-delete as a fallback.
  3. Close other applications that may lock the source folder (sync clients, file explorers, antivirus).
  4. Retry the move after a brief pause if the lock is transient.
  5. If the destination already has conflicting data, manually clean it up before re-attempting.
Defensive patterns

Strategy: try-catch

Try / catch

if err := model.MoveDocs(fromPaths, toBoxID, toPath, callback); err != nil {
    if strings.Contains(err.Error(), conf.Conf.Language(5)[:10]) {
        // Move file failed — check logs for OS-level error
        logging.LogErrorf("move failed, possible lock or cross-device: %s", err)
        // advise user to close locking apps or move within same volume
    }
    return err
}

Prevention

When it happens

Trigger: Cross-notebook MoveDocs where the source document has sub-documents (fromFolder exists). The code at line 1864-1874 constructs absolute paths for both source and destination, removes any pre-existing destination, then calls filelock.Rename. Failure occurs on cross-device renames, permission errors, or if the source folder is locked by another process.

Common situations: Moving a document with many children between notebooks on different mount points (rename fails across filesystems). A file lock from antivirus or sync software on Windows blocks the source folder. The destination directory was removed by a concurrent operation between the IsExist check and the Rename call.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/da33e4373bc471af. Report an issue: GitHub.