{"record":{"id":"0ac4c0882400dfeb","repo":"siyuan-note/siyuan","slug":"conf-language-87-file-tree-reorder","errorCode":null,"errorMessage":"Conf.Language(87)","messagePattern":"Conf\\.Language\\(87\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/file_tree_reorder.go","lineNumber":157,"sourceCode":"\t}\n\tsiblingIDs, err := loadSiblingCustomOrder(box.ID, parentDir, existingSorts)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, id := range siblingIDs {\n\t\tif byID[id] == nil {\n\t\t\treturn nil, fmt.Errorf(\"document [%s] could not be read\", id)\n\t\t}\n\t}\n\tvar fromPaths []string\n\tfor _, id := range sourceIDs {\n\t\tsource := treenode.GetBlockTree(id)\n\t\tif !isSortableDocument(source) || Conf.Box(source.BoxID) == nil {\n\t\t\treturn nil, fmt.Errorf(\"source document [%s] is unavailable\", id)\n\t\t}\n\t\tif source.BoxID == target.BoxID && (target.Path == source.Path ||\n\t\t\tstrings.HasPrefix(target.Path, strings.TrimSuffix(source.Path, \".sy\")+\"/\")) {\n\t\t\treturn nil, errors.New(Conf.Language(87))\n\t\t}\n\t\tif byID[id] != nil {\n\t\t\tcontinue\n\t\t}\n\t\tsourceParent := path.Dir(source.Path)\n\t\tif sourceParent != \"/\" {\n\t\t\tsourceParent += \".sy\"\n\t\t}\n\t\tsourceDocs, _, loadErr := ListDocTree(source.BoxID, sourceParent, util.SortModeCustom, false, true, int(^uint(0)>>1))\n\t\tif loadErr != nil {\n\t\t\treturn nil, loadErr\n\t\t}\n\t\tfor _, doc := range sourceDocs {\n\t\t\tif doc.ID == id {\n\t\t\t\tbyID[id] = doc\n\t\t\t\tbreak\n\t\t\t}\n\t\t}","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/file_tree_reorder.go#L139-L175","documentation":"ReorderDocTree rejects moves where a source document would be moved into itself or one of its descendants: the source shares the target's notebook and the target path equals the source path or lies under it. The message is the localized user-facing string Conf.Language(87) ('Cannot move to this location').","triggerScenarios":"Calling ReorderDocTree where source.BoxID == target.BoxID and target.Path == source.Path or target.Path starts with source.Path minus the .sy suffix plus '/'.","commonSituations":"UI drag dropping a parent document onto its own child; scripted reorders computing a target inside the moved subtree.","solutions":["Choose a target outside the moved source's subtree","In code, guard with a path-prefix check before calling reorderDocs","If moving multiple documents, exclude ancestors of the target from sourceIDs"],"exampleFix":"// before\nreorderDocs([parentID], childID, 'bottom')\n// after\nif (!targetPath.startsWith(parentPath.replace(/\\.sy$/, '') + '/')) {\n  reorderDocs([parentID], childID, 'bottom')\n}","handlingStrategy":"validation","validationCode":"function canMoveTo(sourcePath, targetPath) {\n  return targetPath !== sourcePath && !targetPath.startsWith(sourcePath.replace(/\\.sy$/, '') + '/')\n}","typeGuard":null,"tryCatchPattern":"try { await reorderDocs(sources, target, pos) } catch (e) { if (e.message === L(87)) notifyUser('Cannot move a document into its own subtree') }","preventionTips":["Disable drop targets inside the dragged document's subtree in the UI","Always compare paths before scripted moves","Test multi-select moves for ancestor/descendant overlaps"],"tags":["validation","document-tree","hierarchy","cyclic-move"],"backgroundTag":"invalid-state-transition","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}