siyuan-note/siyuan · error

Conf.Language(5) formatted with box name, path and error

Error message

Conf.Language(5) formatted with box name, path and error

What it means

After SiYuan already tried and retried the physical rename of a .sy file, filelock.Rename still failed; the error is wrapped as localized 'Move notebook [%s] file [%s] failed: %s' (key 5) with the source box name, path, and OS error. This is an I/O-level failure surfaced to the user, distinct from the pre-move validation errors.

Solutions

  1. Read the trailing OS error in the message to identify the underlying cause
  2. Close apps/plugins holding the .sy file and retry the move
  3. Check disk space and that the file is not opened by another SiYuan client, then retry
Defensive patterns

Strategy: try-catch

Validate before calling

const exists = await fileExists(absToPath); if (exists) throw new Error('Destination already occupied, aborting move')

Try / catch

try { await fetchPost('/api/filetree/moveDocs', args) } catch (e) { if (String(e).startsWith('Move notebook')) { logWithOsError(e); /* notify user, keep source data */ } }

Prevention

When it happens

Trigger: filelock.Rename(absFromPath, absToPath) fails during moveDoc — typically the target file appeared mid-move, antivirus/file-locking on Windows holds the .sy, or a cross-device rename occurs.

Common situations: Another client or plugin has the file open; Windows file locks (search indexer, backup tools); running out of disk space; sync conflict writing the target simultaneously.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/ca5187bb8c36866f. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/file.go:1911

	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 9f775e8a12)