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
- Check strings.HasPrefix(toPath, strings.TrimSuffix(fromPath, '.sy') + '/') before calling and skip such pairs
- Move the documents to a sibling folder instead of into themselves
- 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
- Filter ancestors of the target out of fromPaths before moving
- In bulk jobs, sort sources so parents are never moved into their own subtree
- Test move scripts on a scratch notebook first
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)