siyuan-note/siyuan · error

Conf.Language(87)

Error message

Conf.Language(87)

What it means

MoveDocs rejects moves where the destination path is the source document itself or one of its descendants ('Cannot move to this location', key 87). Moving a document into itself would create a cycle, so the check runs before any filesystem change, guaranteeing the failed call has no side effects.

Solutions

  1. Check strings.HasPrefix(toPath, strings.TrimSuffix(fromPath, '.sy') + '/') before calling and skip such pairs
  2. Move the documents to a sibling folder instead of into themselves
  3. Filter source list so no document is an ancestor of the target

Example fix

// before
await fetchPost('/api/filetree/moveDocs', {fromPaths: ['/a.sy'], toNotebook: boxID, toPath: '/a/b'})
// after
if (toPath !== '/a.sy' && !toPath.startsWith('/a/')) {
  await fetchPost('/api/filetree/moveDocs', {fromPaths: ['/a.sy'], toNotebook: boxID, toPath: toPath})
}
Defensive patterns

Strategy: validation

Validate before calling

const isSelfOrDescendant = (fromPath, toPath) => toPath === fromPath || toPath.startsWith(fromPath.replace(/\.sy$/, '') + '/'); fromPaths = fromPaths.filter(p => !isSelfOrDescendant(p, toPath))

Try / catch

try { await fetchPost('/api/filetree/moveDocs', args) } catch (e) { if (String(e).includes('Cannot move to this location')) { /* skip or recompute target */ } }

Prevention

When it happens

Trigger: moveDocs where toPath equals a fromPath or lies under it (e.g. moving /a.sy to /a/b); also triggered when trimming '.sy' and the target is a child path of the source.

Common situations: Bulk-move scripts with computed target paths; UI drag onto a collapsed ancestor; recursive batch jobs that skip the parent check.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/file.go:1713

}

func MoveDocs(fromPaths []string, toBoxID, toPath string, callback any) (err error) {
	toBox := Conf.Box(toBoxID)
	if nil == toBox {
		err = errors.New(Conf.Language(0))
		return
	}
	toPath = normalizeBoxDocTarget(toBoxID, toPath)
	pathsBoxes, err := getBoxesByPathsStrict(fromPaths)
	if err != nil {
		return
	}

	// 在移动任何文档前拒绝自身及后代目标,避免调用方将未执行的移动视为成功。
	for _, fromPath := range fromPaths {
		if fromBox := pathsBoxes[fromPath]; nil != fromBox && fromBox.ID == toBoxID &&
			(toPath == fromPath || strings.HasPrefix(toPath, strings.TrimSuffix(fromPath, ".sy")+"/")) {
			return errors.New(Conf.Language(87))
		}
	}
	fromPaths = util.FilterMoveDocFromPaths(fromPaths, toPath)
	if 1 > len(fromPaths) {
		return
	}

	fromPaths = orderMoveDocPaths(fromPaths, pathsBoxes)

	for _, fromPath := range fromPaths {
		fromBox := pathsBoxes[fromPath]
		if nil != fromBox && IsBoxDocPath(fromBox.ID, fromPath) {
			return errors.New(Conf.Language(341))
		}
	}

	if 1 == len(fromPaths) {
		// 移动到自己的父文档下的情况相当于不移动,直接返回

View on GitHub (pinned to 9f775e8a12)