siyuan-note/siyuan · error
notebook [ ] is closed; run `notebook open --id ` first
Error message
notebook [%s] is closed; run `notebook open --id %s` first
What it means
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.
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.
Example fix
// before siyuan notebook rename --id 20240101120000-abcd123 --name "New" // closed // after siyuan notebook open --id 20240101120000-abcd123 siyuan notebook rename --id 20240101120000-abcd123 --name "New"
Defensive patterns
Strategy: try-catch
Validate before calling
# check the notebook is open before writing open_ids=$(curl -s http://127.0.0.1:6806/api/notebook/lsNotebooks | jq -r '.data.notebooks[].id') echo "$open_ids" | grep -q "$BOX_ID" || siyuan notebook open --id "$BOX_ID"
Try / catch
if ! siyuan notebook rename --id "$BOX_ID" --name "$NAME"; then siyuan notebook open --id "$BOX_ID" siyuan notebook rename --id "$BOX_ID" --name "$NAME" fi
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- appearance files not found at
- --attr is required (format: name=value)
- --av and --ids are required
- --av and --key are required
- --av is required
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/96104b4df6b29b3b.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/cli/cmd/notebook.go:92
return nil
}
id, err := model.CreateBox(name)
if err != nil {
return err
}
if _, err = model.Mount(id); err != nil {
return fmt.Errorf("notebook [%s] was created but could not be opened: %w", id, err)
}
model.AppendPushReloadFiletreeEntry()
fmt.Println(id)
return nil
},
}
func formatNotebookWriteError(boxID string, err error) error {
if errors.Is(err, model.ErrBoxClosed) {
return fmt.Errorf("notebook [%s] is closed; run `notebook open --id %s` first", boxID, boxID)
}
if errors.Is(err, model.ErrBoxNotFound) {
return fmt.Errorf("notebook [%s] not found", boxID)
}
return err
}
var notebookRemoveCmd = &cobra.Command{
Use: "remove --id <id>",
Short: "Remove a notebook",
RunE: func(cmd *cobra.Command, args []string) error {
id, _ := cmd.Flags().GetString("id")
if id == "" {
return fmt.Errorf("--id is required")
}
if dryRun {
fmt.Printf("[dry-run] Would remove notebook %s\n", id)View on GitHub (pinned to 9f775e8a12)