{"record":{"id":"f6adcad15020e923","repo":"siyuan-note/siyuan","slug":"document-s-not-found-in-opened-and-unlocked-not","errorCode":null,"errorMessage":"document [%s] not found in opened and unlocked notebooks","messagePattern":"document \\[(.+?)\\] not found in opened and unlocked notebooks","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/file.go","lineNumber":2936,"sourceCode":"\t\t\treturn ret, fmt.Errorf(\"notebook [%s] not found\", item.ID)\n\t\t}\n\t\tnotebookPlans = append(notebookPlans, &notebookSortPlan{item: item, box: box})\n\t}\n\n\tdocPlans := make([]*docSortPlan, 0, len(docSorts))\n\tdocIDs := map[string]struct{}{}\n\tfor _, item := range docSorts {\n\t\tif nil == item {\n\t\t\treturn ret, errors.New(\"document sort item must not be nil\")\n\t\t}\n\t\tif _, ok := docIDs[item.ID]; ok {\n\t\t\treturn ret, fmt.Errorf(\"duplicate document ID [%s]\", item.ID)\n\t\t}\n\t\tdocIDs[item.ID] = struct{}{}\n\n\t\tbt := treenode.GetBlockTree(item.ID)\n\t\tif nil == bt || nil == openedBoxes[bt.BoxID] {\n\t\t\treturn ret, fmt.Errorf(\"document [%s] not found in opened and unlocked notebooks\", item.ID)\n\t\t}\n\t\tif bt.ID != bt.RootID || \"d\" != bt.Type || IsBoxDoc(bt.BoxID, bt.RootID) {\n\t\t\treturn ret, fmt.Errorf(\"block [%s] is not a sortable document\", item.ID)\n\t\t}\n\t\tif nil == boxes[bt.BoxID] {\n\t\t\treturn ret, fmt.Errorf(\"notebook [%s] not found for document [%s]\", bt.BoxID, item.ID)\n\t\t}\n\t\tdocPlans = append(docPlans, &docSortPlan{item: item, boxID: bt.BoxID, parentPath: path.Dir(bt.Path)})\n\t}\n\n\tdocGroups := map[string]*docSortGroup{}\n\tfor _, plan := range docPlans {\n\t\tgroup := docGroups[plan.boxID]\n\t\tif nil == group {\n\t\t\tconfPath := filepath.Join(util.DataDir, plan.boxID, \".siyuan\", \"sort.json\")\n\t\t\tfullSortIDs, readErr := readSortConfMap(confPath)\n\t\t\tif readErr != nil {\n\t\t\t\treturn ret, readErr","sourceCodeStart":2918,"sourceCodeEnd":2954,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/file.go#L2918-L2954","documentation":"A sort item must reference a sortable document: its block-tree record must be a root node (bt.ID == bt.RootID) of type \"d\" and must not itself be the notebook's box doc entry (IsBoxDoc). Otherwise the kernel rejects it with \"block [%s] is not a sortable document\". This prevents attempts to reorder headings, child blocks, or virtual box-level entries.","triggerScenarios":"Passing a non-root block ID (heading, paragraph, child document in a doc tree), a container/attribute-view block type other than \"d\", or the box's internal doc ID into the document sort API.","commonSituations":"Client bug using selected-block IDs instead of the document root ID; attempting to sort child documents of a document tree (which are regular blocks, not siblings under a parent path); scripting against exported IDs that point at headings.","solutions":["Use the document's root ID (RootID from the block tree / the .sy filename) instead of an inner block ID","Only sort documents that appear as siblings under a parent path in a notebook; child blocks cannot be reordered via this API","Filter the sort list to items whose block-tree type is \"d\" and whose ID equals RootID"],"exampleFix":"// before: heading block ID passed in\nsortDocs([\"20240101120000-abcdefgh\"])\n// after: resolve to the document root\nconst rootId = getBlockTree(blockId).root_id;\nsortDocs([rootId])","handlingStrategy":"type-guard","validationCode":"const bt = await api.getBlockTree(id);\nif (!bt || bt.id !== bt.root_id || bt.type !== 'd') throw new Error('not a sortable document root');","typeGuard":"const isDocRoot = (bt) => bt != null && bt.id === bt.root_id && bt.type === 'd';","tryCatchPattern":"try { await api.sortDocs(items); } catch (e) { if (String(e).includes('is not a sortable document')) { const roots = items.map(i => toRootId(i.id)); await api.sortDocs(roots); } else { throw e; } }","preventionTips":["Resolve any block ID to its RootID before sorting","Only send IDs that correspond to .sy filenames in the notebook","Never attempt to order child blocks/headings via the document sort API"],"tags":["go","blocktree","document","invalid-argument"],"backgroundTag":"incompatible-source-type","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"}