siyuan-note/siyuan · error
invalid box ID [%s]
Error message
invalid box ID [%s]
What it means
First guard in ensureBoxDoc0 (kernel/model/box_doc.go): the boxID argument must satisfy ast.IsNodeIDPattern before anything else runs. Callers are notebook mount (kernel/model/mount.go:475), config-driven ensure (kernel/model/conf.go:1311) and repo sync apply (kernel/model/repository.go:2509). The error signals a malformed notebook identifier in persisted state or a bad API argument, not a runtime failure.
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 afa823b6b4)
Solutions
- Verify the notebook ID passed in: it must match ^\d{14}-[a-z0-9]{7}$
- If a hand-created folder caused it, rename it to a valid unique node ID or remove it and create the notebook through SiYuan's UI/API
- If conf.json lists a malformed notebook, remove that entry and restart the kernel
- For repo sync, inspect the incoming snapshot's notebook IDs before applying
Example fix
// before boxID := "my-notebook" ensureBoxDoc0(boxID) // after boxID := "20240601120000-newbox01" ensureBoxDoc0(boxID)
Defensive patterns
Strategy: type-guard
Type guard
// Go predicate mirroring ast.IsNodeIDPattern
var nodeIDRe = regexp.MustCompile(`^\d{14}-[a-z0-9]{7}$`)
func isValidNodeID(id string) bool {
return nodeIDRe.MatchString(id)
}
// use before the call
if !isValidNodeID(boxID) {
return fmt.Errorf("refusing to ensure box doc: bad notebook ID %q", boxID)
}
_, _ = model.EnsureBoxDoc(boxID) Try / catch
if _, err := model.EnsureBoxDoc(boxID); err != nil {
if strings.Contains(err.Error(), "invalid box ID") {
// input problem: fix the caller, do not retry
}
return err
} Prevention
- Always take notebook IDs from /api/notebook/lsNotebooks output
- Create notebooks via the API, never by adding folders under data/
- Validate repo/sync inputs that carry box IDs before applying snapshots
When it happens
Trigger: A notebook folder under data/ whose name is not a 20-char node ID (hand-created folder) reaches mount; a corrupted conf.json notebooks list; a repo snapshot referencing a box with a garbage ID during sync apply; calling notebook APIs with arbitrary strings instead of IDs from /api/notebook/lsNotebooks.
Common situations: Users creating notebook folders manually in the file manager; workspace files touched by external tools; damaged sync snapshots; scripts calling /api/notebook/* with made-up IDs.
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
- invalid box document ID [%s]
- box document ID [%s] does not match box ID [%s]
- box document ID [%s] is already in use
- invalid notebook ID
- path belongs to encrypted notebook [%s]
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/a19632856e32a71c.
Report an issue: GitHub.