{"record":{"id":"dd293178b23ef630","repo":"siyuan-note/siyuan","slug":"document-s-is-unavailable","errorCode":null,"errorMessage":"document [%s] is unavailable","messagePattern":"document \\[(.+?)\\] is unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/pinned_docs.go","lineNumber":193,"sourceCode":"\t\t\treturn fmt.Errorf(\"invalid document ID [%s]\", id)\n\t\t}\n\t\tif selected[id] {\n\t\t\tcontinue\n\t\t}\n\t\tselected[id] = true\n\t\tif action == \"unpin\" {\n\t\t\tcontinue\n\t\t}\n\t\tbt := treenode.GetBlockTree(id)\n\t\tif bt != nil && IsEncryptedBox(bt.BoxID) {\n\t\t\treturn fmt.Errorf(\"%s\", Conf.Language(396))\n\t\t}\n\t\tif !isPinnableDocument(bt) {\n\t\t\treturn fmt.Errorf(\"document [%s] cannot be pinned\", id)\n\t\t}\n\t\tbox := Conf.Box(bt.BoxID)\n\t\tif box == nil || box.Stat(bt.Path) == nil {\n\t\t\treturn fmt.Errorf(\"document [%s] is unavailable\", id)\n\t\t}\n\t\tial := box.docIAL(bt.Path)\n\t\tif ial == nil {\n\t\t\treturn fmt.Errorf(\"cannot read pinned document [%s]\", id)\n\t\t}\n\t\tif id != bt.BoxID && ial[DocHiddenAttr] == \"true\" {\n\t\t\treturn fmt.Errorf(\"document [%s] cannot be pinned\", id)\n\t\t}\n\t\trefs = append(refs, pinnedDocRef{ID: id, Notebook: bt.BoxID})\n\t}\n\tif action == \"pin\" && selected[targetID] {\n\t\treturn nil\n\t}\n\tremaining := []pinnedDocRef{}\n\tfor _, ref := range stored.Docs {\n\t\tif !selected[ref.ID] {\n\t\t\tremaining = append(remaining, ref)\n\t\t}","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/pinned_docs.go#L175-L211","documentation":"After resolving the block-tree record, UpdatePinnedDocs looks up the owning notebook via Conf.Box(bt.BoxID) and stats the .sy file at bt.Path. If the notebook is closed (Conf.Box returns nil) or the document file is missing on disk (Stat returns nil), the document cannot be pinned and this error is returned.","triggerScenarios":"Pinning a document whose notebook is closed in the current workspace, or whose .sy file no longer exists (deleted externally, path changed, or block-tree entry stale after sync/move).","commonSituations":"Notebook closed by the user or by another window; document removed by an external sync client while the block-tree index still references it; workspace switched so the notebook is not opened.","solutions":["Open the notebook (Conf.OpenBox / the UI) before pinning its documents.","Rebuild the index so stale block-tree entries are removed, then retry with an existing document.","Verify the .sy file exists under data/<boxID>/<path> and restore it if it was deleted.","Pick a document from an opened notebook."],"exampleFix":"// before\nmodel.UpdatePinnedDocs([]string{docID}, \"pin\", \"\", false)\n// after\nif box := model.Conf.Box(bt.BoxID); box == nil || box.Closed {\n    return errors.New(\"open the notebook before pinning its documents\")\n}\nmodel.UpdatePinnedDocs([]string{docID}, \"pin\", \"\", false)","handlingStrategy":"validation","validationCode":"box := model.Conf.Box(bt.BoxID)\nif box == nil {\n    return errors.New(\"notebook is closed\")\n}\nif box.Stat(bt.Path) == nil {\n    return errors.New(\"document file missing on disk\")\n}","typeGuard":"func docOnDisk(bt *treenode.BlockTree) bool {\n    box := model.Conf.Box(bt.BoxID)\n    return box != nil && box.Stat(bt.Path) != nil\n}","tryCatchPattern":"if err := model.UpdatePinnedDocs(ids, \"pin\", \"\", false); err != nil {\n    if strings.Contains(err.Error(), \"is unavailable\") {\n        // open the notebook or refresh the index, then retry\n    }\n}","preventionTips":["Open target notebooks before batch pin operations","Rebuild the index after external file changes or sync","Verify .sy files exist before referencing document IDs","Handle workspace switches that close all notebooks"],"tags":["pinned-docs","file-not-found","notebook-closed"],"backgroundTag":"resource-not-found","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"}