{"record":{"id":"96104b4df6b29b3b","repo":"siyuan-note/siyuan","slug":"notebook-s-is-closed-run-notebook-open-id","errorCode":null,"errorMessage":"notebook [%s] is closed; run `notebook open --id %s` first","messagePattern":"notebook \\[(.+?)\\] is closed; run `notebook open --id (.+?)` first","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/cli/cmd/notebook.go","lineNumber":92,"sourceCode":"\t\t\treturn nil\n\t\t}\n\n\t\tid, err := model.CreateBox(name)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif _, err = model.Mount(id); err != nil {\n\t\t\treturn fmt.Errorf(\"notebook [%s] was created but could not be opened: %w\", id, err)\n\t\t}\n\t\tmodel.AppendPushReloadFiletreeEntry()\n\t\tfmt.Println(id)\n\t\treturn nil\n\t},\n}\n\nfunc formatNotebookWriteError(boxID string, err error) error {\n\tif errors.Is(err, model.ErrBoxClosed) {\n\t\treturn fmt.Errorf(\"notebook [%s] is closed; run `notebook open --id %s` first\", boxID, boxID)\n\t}\n\tif errors.Is(err, model.ErrBoxNotFound) {\n\t\treturn fmt.Errorf(\"notebook [%s] not found\", boxID)\n\t}\n\treturn err\n}\n\nvar notebookRemoveCmd = &cobra.Command{\n\tUse:   \"remove --id <id>\",\n\tShort: \"Remove a notebook\",\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tid, _ := cmd.Flags().GetString(\"id\")\n\t\tif id == \"\" {\n\t\t\treturn fmt.Errorf(\"--id is required\")\n\t\t}\n\n\t\tif dryRun {\n\t\t\tfmt.Printf(\"[dry-run] Would remove notebook %s\\n\", id)","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/cli/cmd/notebook.go#L74-L110","documentation":"formatNotebookWriteError maps model.ErrBoxClosed (returned by notebook write operations on a closed notebook) into an actionable message telling the user the notebook is closed and to run `notebook open --id <id>` first. SiYuan requires notebooks to be open (mounted/indexed) before documents can be written into them.","triggerScenarios":"Any notebook write command (e.g. notebook rename/remove flows wrapping model calls) where the underlying model call returns model.ErrBoxClosed because the target notebook was closed via `notebook close` or was never opened.","commonSituations":"Scripting against a notebook that was closed earlier in the session; a fresh workspace where the notebook is present on disk but not yet opened; renaming a notebook that the UI has closed.","solutions":["Run `siyuan notebook open --id <boxID>` to open the notebook, then retry the operation.","List open notebooks first to check state before performing write commands.","In scripts, open the notebook as a pre-step before any write operations."],"exampleFix":"// before\nsiyuan notebook rename --id 20240101120000-abcd123 --name \"New\"  // closed\n// after\nsiyuan notebook open --id 20240101120000-abcd123\nsiyuan notebook rename --id 20240101120000-abcd123 --name \"New\"","handlingStrategy":"try-catch","validationCode":"# check the notebook is open before writing\nopen_ids=$(curl -s http://127.0.0.1:6806/api/notebook/lsNotebooks | jq -r '.data.notebooks[].id')\necho \"$open_ids\" | grep -q \"$BOX_ID\" || siyuan notebook open --id \"$BOX_ID\"","typeGuard":null,"tryCatchPattern":"if ! siyuan notebook rename --id \"$BOX_ID\" --name \"$NAME\"; then\n  siyuan notebook open --id \"$BOX_ID\"\n  siyuan notebook rename --id \"$BOX_ID\" --name \"$NAME\"\nfi","preventionTips":["Open notebooks before any write command","Check notebook open state via lsNotebooks in scripts","Remember notebooks closed via the UI or `notebook close` stay closed"],"tags":["cli","notebook-state","closed-notebook"],"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"}