siyuan-note/siyuan · error
invalid box ID [ ]
Error message
invalid box ID [%s]
What it means
ensureBoxDoc0 validates that the given box ID looks like a SiYuan node ID (32-char lowercase hex, per ast.IsNodeIDPattern) before creating or locating the box's hidden document. The box ID here is a notebook identifier that must follow the node ID format; anything else is rejected immediately with this formatted message echoing the offending value. It is thrown before any disk or database lookups.
Solutions
- Pass a valid notebook ID (32 lowercase hex characters) obtained from Conf.GetBox / listNotebooks output
- Trim whitespace and normalize case of the box ID before calling
- If generating a new ID, use ast.NewNodeID() rather than a custom string
Example fix
// before
EnsureBoxDoc("my notebook")
// after
box := Conf.GetBox("20240101120000-abcdef0123456789")
if box != nil {
EnsureBoxDoc(box.ID)
} Defensive patterns
Strategy: validation
Validate before calling
function isValidBoxID(id) {
return typeof id === "string" && /^[0-9]{14}-[0-9a-z]{16}$/.test(id);
}
if (!isValidBoxID(boxID)) throw new Error("refusing to call EnsureBoxDoc with invalid ID"); Type guard
const isBoxID = (v: unknown): v is string => typeof v === "string" && /^[0-9]{14}-[0-9a-z]{16}$/.test(v); Prevention
- Always take box IDs from Conf.GetBox or notebook listing output, never hand-build them
- Trim and lowercase IDs coming from external scripts before use
- Keep a single helper that validates node-ID format before any kernel call
When it happens
Trigger: Calling model.EnsureBoxDoc or createBox with a boxID string that is empty, contains invalid characters, or is otherwise not a valid ast node ID pattern.
Common situations: Scripts or plugins constructing a notebook ID manually instead of using one returned by listNotebooks; truncated or uppercased IDs from external tools; passing a human-readable notebook name where an ID is expected.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/a19632856e32a71c.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/box_doc.go:130
var bt *treenode.BlockTree
if "" == boxID {
bt = treenode.GetBlockTree(id)
} else {
bt = treenode.GetBlockTreeInBox(id, boxID)
}
return nil != bt && IsBoxDoc(bt.BoxID, bt.RootID)
}
func EnsureBoxDoc(boxID string) (boxDocID string, err error) {
createDocLock.Lock()
defer createDocLock.Unlock()
return ensureBoxDoc0(boxID)
}
// ensureBoxDoc0 的调用方必须持有 createDocLock。
func ensureBoxDoc0(boxID string) (boxDocID string, err error) {
if !ast.IsNodeIDPattern(boxID) {
return "", fmt.Errorf("invalid box ID [%s]", boxID)
}
box := Conf.GetBox(boxID)
if nil == box {
return "", ErrBoxNotFound
}
if !IsBoxDocEnabled() {
return
}
boxDocID = boxID
boxDocID, err = findBoxDoc(box)
if err != nil {
return "", err
}
created, changed := false, false
if "" == boxDocID {View on GitHub (pinned to 9f775e8a12)