siyuan-note/siyuan · error
notebook [%s] is closed; run `notebook open --id %s` first
Error message
notebook [%s] is closed; run `notebook open --id %s` first
What it means
Produced by `formatNotebookWriteError` when a notebook write operation returned `model.ErrBoxClosed`. The helper wraps the sentinel into an actionable message telling the caller to open the notebook first. It is returned by notebook write subcommands (rename, configure, document operations) whose target box is currently closed (unmounted).
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 251596fc0d)
Solutions
- Open the notebook first: `siyuan notebook open --id <id>`, then retry the write
- Confirm the notebook is open with `siyuan notebook list` before scripting writes
- If open reports the box not found, the ID is wrong or the box was removed
Example fix
// before siyuan notebook rename --id 20240101-xyz --name New # -> error: notebook [20240101-xyz] is closed; run `notebook open --id 20240101-xyz` first // after siyuan notebook open --id 20240101-xyz && siyuan notebook rename --id 20240101-xyz --name New
Defensive patterns
Strategy: validation
Validate before calling
// Guard notebook writes by checking mount state first:
boxes, _ := model.ListNotebooks()
opened := false
for _, b := range boxes {
if b.ID == boxID && b.Opened { opened = true; break }
}
if !opened {
if _, err := model.Mount(boxID); err != nil { return err }
} Try / catch
// Match the sentinel before surfacing a generic error:
if errors.Is(err, model.ErrBoxClosed) {
// auto-open then retry, or instruct the user
if _, mErr := model.Mount(boxID); mErr == nil { /* retry op */ }
} Prevention
- Run `notebook list` to confirm a box is open before writing to it
- Open notebooks explicitly (`notebook open --id`) at the start of any write script
- Handle `ErrBoxClosed` by mounting then retrying, not by aborting
- A created-but-unmounted notebook (error 238) will trip this on the next write
When it happens
Trigger: Calling a notebook write command against an ID whose box is closed — e.g. after `notebook close`, after a restart that did not auto-mount, or on a box the user manually closed in the GUI. `formatNotebookWriteError` matches the error with `errors.Is(err, model.ErrBoxClosed)` and formats the remediation hint.
Common situations: Notebooks are closed by default after certain operations or manually via the GUI; scripts that assume all notebooks are open; operating on a freshly created notebook whose mount failed (see error 238).
Related errors
- notebook [%s] was created but could not be opened: %w
- path belongs to encrypted notebook [%s]: %s
- --notebook is required
- --notebook is required
- parent path not found: %s
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/96104b4df6b29b3b.
Report an issue: GitHub.