siyuan-note/siyuan · error
invalid id
Error message
invalid id
What it means
Sentinel error model.ErrInvalidID (kernel/model/tree.go:208). It flags identifiers that fail format validation rather than lookup - the attribute view render path returns it for malformed av/block ids (attribute_view_render.go:394, 1047, 1083, 1124, 1189), and kernel tests assert it for invalid attribute view inputs. Unlike ErrBlockNotFound/ErrTreeNotFound, the id never gets as far as a blocktree lookup: its shape is wrong.
Solutions
- Use ids exactly as returned by the kernel (block info queries, av search/list endpoints)
- Validate the id shape client-side before calling (see type guard)
- Match with errors.Is(err, model.ErrInvalidID) to distinguish 'bad format' from 'not found' in error handling
Defensive patterns
Strategy: type-guard
Validate before calling
// Reject malformed ids client-side before attribute-view calls:
var idRe = regexp.MustCompile(`^[0-9]{14}-[a-z0-9]{7}$`)
if !idRe.MatchString(avID) {
return fmt.Errorf("invalid id format: %s", avID)
} Type guard
func isValidNodeID(id string) bool {
// SiYuan node ids: 14-digit timestamp + '-' + 7-char suffix
matched, _ := regexp.MatchString(`^[0-9]{14}-[a-z0-9]{7}$`, id)
return matched
} Try / catch
if err := renderAV(avID); err != nil {
if errors.Is(err, model.ErrInvalidID) {
// format problem - fix the id source, retrying will not help
}
} Prevention
- Only use ids returned by kernel APIs (block info, av list/search)
- Validate id shape at input boundaries (HTTP params, plugin settings)
- Log the offending id when ErrInvalidID fires to find which producer created it
When it happens
Trigger: Feeding a self-invented, truncated, or wrongly-typed id into attribute view render/getAttributeView* APIs; passing an empty or whitespace id where a kernel-issued id is required.
Common situations: Plugins generating their own ids instead of using ids the kernel returned; copy-paste truncation; substituting a document path or av name where an id belongs.
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
- at least one visible view is required
- attribute view custom color index
- attribute view custom color must not be null
- attribute view custom colors count exceeds the
- attribute view custom colors must not be empty
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/18fcb60917735226.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/tree.go:208
}
}
ret, err = dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)
if err != nil {
logging.LogErrorf("parse json to tree [%s] failed: %s", localPath, err)
return
}
return
}
var (
ErrBoxNotFound = errors.New("notebook not found")
ErrBoxClosed = errors.New("notebook closed")
ErrBlockNotFound = errors.New("block not found")
ErrTreeNotFound = errors.New("tree not found")
ErrIndexing = errors.New("indexing")
ErrBoxUnindexed = errors.New("notebook unindexed")
ErrInvalidID = errors.New("invalid id")
)
func LoadTreeByBlockIDWithReindex(id string) (ret *parse.Tree, err error) {
return LoadTreeByBlockIDWithReindexInBox(id, "")
}
// LoadTreeByBlockIDWithReindexInBox 与 LoadTreeByBlockIDWithReindex 一致,但按 boxID 路由 blocktree 查询。
func LoadTreeByBlockIDWithReindexInBox(id, boxID string) (ret *parse.Tree, err error) {
if "" == id {
logging.LogWarnf("block id is empty")
return nil, ErrTreeNotFound
}
bt := treenode.GetBlockTreeInBox(id, boxID)
if nil == bt && "" == boxID {
// boxID 未知时(如通用打开入口),遍历所有已打开的加密笔记本查找
for _, encBoxID := range treenode.GetOpenedEncryptedBoxIDs() {
if encBT := treenode.GetBlockTreeInBox(id, encBoxID); nil != encBT {View on GitHub (pinned to afa823b6b4)