{"record":{"id":"8eeddeea6e85abc5","repo":"siyuan-note/siyuan","slug":"target-document-s-is-not-in-an-opened-and-unloc","errorCode":null,"errorMessage":"target document [%s] is not in an opened and unlocked notebook","messagePattern":"target document \\[(.+?)\\] is not in an opened and unlocked notebook","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/file.go","lineNumber":2692,"sourceCode":"\tNotebook   string `json:\"notebook,omitempty\"`\n\tParentPath string `json:\"parentPath,omitempty\"`\n}\n\n// ReorderDocs 将同级文档移动到目标文档之前或之后。\nfunc ReorderDocs(sourceIDs []string, targetID, position string) (ret *ReorderResult, err error) {\n\tret = &ReorderResult{}\n\tif err = validateReorderArgs(sourceIDs, targetID, position); nil != err {\n\t\treturn\n\t}\n\n\tFlushTxQueue()\n\ttarget := treenode.GetBlockTree(targetID)\n\tif !isSortableDocument(target) {\n\t\treturn ret, fmt.Errorf(\"target document [%s] not found\", targetID)\n\t}\n\tbox := Conf.Box(target.BoxID)\n\tif nil == box {\n\t\treturn ret, fmt.Errorf(\"target document [%s] is not in an opened and unlocked notebook\", targetID)\n\t}\n\tparentPath := path.Dir(target.Path)\n\tfor _, sourceID := range sourceIDs {\n\t\tsource := treenode.GetBlockTree(sourceID)\n\t\tif !isSortableDocument(source) {\n\t\t\treturn ret, fmt.Errorf(\"source document [%s] not found\", sourceID)\n\t\t}\n\t\tif source.BoxID != target.BoxID || path.Dir(source.Path) != parentPath {\n\t\t\treturn ret, fmt.Errorf(\"source document [%s] is not a sibling of target document [%s]\", sourceID, targetID)\n\t\t}\n\t}\n\n\tfileTreeSortLock.Lock()\n\tconfPath := filepath.Join(util.DataDir, box.ID, \".siyuan\", \"sort.json\")\n\tfullSortIDs, readErr := readSortConfMap(confPath)\n\tif nil != readErr {\n\t\tfileTreeSortLock.Unlock()\n\t\treturn ret, readErr","sourceCodeStart":2674,"sourceCodeEnd":2710,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/file.go#L2674-L2710","documentation":"After locating the target document, the kernel looks up its notebook with Conf.Box. If the notebook is nil — meaning it is closed, not currently open in the workspace, or unknown — the reorder is refused because documents in closed/unlocked-away notebooks must not be mutated.","triggerScenarios":"Reordering documents whose target lives in a notebook that was closed by the user; the notebook ID was mistyped so Conf.Box finds no matching opened notebook; workspace was switched and the notebook is no longer loaded.","commonSituations":"Automations running against notebooks the user closed; sync tooling operating on notebooks outside the opened set; stale references after removing a notebook from the workspace.","solutions":["Open the target document's notebook in the SiYuan UI (or add it back to opened notebooks) before reordering","Confirm the notebook ID in the request matches an opened notebook via the notebooks listing API","Re-resolve target.BoxID from a fresh GetBlockTree lookup instead of a cached value","Remove or skip the operation for documents in closed notebooks in your automation logic"],"exampleFix":"// before\nreorderDocs(srcIDs, targetID, \"after\") // target notebook may be closed\n// after\nif isNotebookOpen(notebookIDOf(targetID)) {\n    reorderDocs(srcIDs, targetID, \"after\")\n}","handlingStrategy":"validation","validationCode":"const nb = await getNotebook(target.notebookId)\nif (!nb || nb.closed) throw new Error(\"open the notebook before reordering\")","typeGuard":"const isOpenNotebook = (nb) => !!nb && nb.closed === false","tryCatchPattern":"try { await api.reorderDocs(src, targetID, pos) } catch (e) { if (String(e).includes(\"opened and unlocked notebook\")) { await openNotebook(target.notebookId); return retryOnce() } throw e }","preventionTips":["Check the notebooks listing for closed state before mutating documents","Skip closed notebooks explicitly in automation job filters","Re-open notebooks programmatically when operating across workspace switches"],"tags":["go","kernel","notebook","state"],"backgroundTag":"permission-denied","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"}