{"record":{"id":"4ea9007d856a5517","repo":"siyuan-note/siyuan","slug":"errboxclosed","errorCode":"ErrBoxClosed","errorMessage":"notebook closed","messagePattern":"notebook closed","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/tree.go","lineNumber":211,"sourceCode":"\t\t\tlogging.LogErrorf(\"decrypt tree [path=%s] failed: %s\", localPath, err)\n\t\t\treturn\n\t\t}\n\t}\n\n\tif err = treenode.CheckSpecJSON(data); nil != err {\n\t\treturn\n\t}\n\tret, err = dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"parse json to tree [%s] failed: %s\", localPath, err)\n\t\treturn\n\t}\n\treturn\n}\n\nvar (\n\tErrBoxNotFound   = errors.New(\"notebook not found\")\n\tErrBoxClosed     = errors.New(\"notebook closed\")\n\tErrBlockNotFound = errors.New(\"block not found\")\n\tErrTreeNotFound  = errors.New(\"tree not found\")\n\tErrIndexing      = errors.New(\"indexing\")\n\tErrBoxUnindexed  = errors.New(\"notebook unindexed\")\n\tErrInvalidID     = errors.New(\"invalid id\")\n)\n\nfunc LoadTreeByBlockIDWithReindex(id string) (ret *parse.Tree, err error) {\n\treturn LoadTreeByBlockIDWithReindexInBox(id, \"\")\n}\n\n// LoadTreeByBlockIDWithReindexInBox 与 LoadTreeByBlockIDWithReindex 一致，但按 boxID 路由 blocktree 查询。\nfunc LoadTreeByBlockIDWithReindexInBox(id, boxID string) (ret *parse.Tree, err error) {\n\tif \"\" == id {\n\t\tlogging.LogWarnf(\"block id is empty\")\n\t\treturn nil, ErrTreeNotFound\n\t}\n","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/tree.go#L193-L229","documentation":"ErrBoxClosed is the sentinel error indicating the target notebook exists but is closed; most write and index operations refuse to touch closed notebooks. Callers such as the CLI formatNotebookWriteError translate it into a hint telling the user to run `notebook open --id <boxID>` first.","triggerScenarios":"Writing to or reading docs of a notebook whose .si/config was closed via /api/notebook/closeNotebook (or the UI); the CLI notebook write/import paths hit it and formatNotebookWriteError rewraps it with the open command; getOpenedBox rejects a closed box.","commonSituations":"User closed the notebook in the UI while automation/CLI scripts still target it; headless scripts operate on notebooks that default to closed after workspace restore; a plugin runs before the notebook is opened at boot.","solutions":["Open the notebook first: POST /api/notebook/openNotebook {\"notebook\": \"<boxID>\"} or run `siyuan-kernel notebook open --id <boxID>`","Check notebook state with lsNotebooks before writing and open it if closed","In Go callers, branch on errors.Is(err, model.ErrBoxClosed) to give the user an actionable message","Ensure workspace boot/open sequence completes before scripts that touch the notebook run"],"exampleFix":"// before\nerr := writeDoc(boxID, path, data)\nif err != nil { return err }\n\n// after\nif err != nil {\n    if errors.Is(err, model.ErrBoxClosed) {\n        return fmt.Errorf(\"notebook [%s] is closed; run `notebook open --id %s` first\", boxID, boxID)\n    }\n    return err\n}","handlingStrategy":"validation","validationCode":"// TypeScript: check notebook state and open if closed before writing\nconst conf = await fetchPost('/api/notebook/lsNotebooks', {});\nconst nb = conf.data.notebooks.find(n => n.id === boxID);\nif (nb && nb.closed) await fetchPost('/api/notebook/openNotebook', { notebook: boxID });","typeGuard":"function isBoxClosed(err: unknown): err is Error {\n  return err instanceof Error && err.message === 'notebook closed';\n}","tryCatchPattern":"// Go\nif errors.Is(err, model.ErrBoxClosed) {\n    return fmt.Errorf(\"notebook [%s] is closed; run `notebook open --id %s` first\", boxID, boxID)\n}","preventionTips":["Open the notebook programmatically before headless/CLI write operations","Check the notebook's closed flag in lsNotebooks output before automation runs","Sequence scripts after workspace boot completes so target notebooks are open"],"tags":["go","kernel","notebook","closed-state"],"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"}