siyuan-note/siyuan · error · ErrInvalidID
invalid id
Error message
invalid id
What it means
Sentinel error ErrInvalidID declared at tree.go:208 ('invalid id'). Returned when an ID fails format validation — primarily in the Attribute View subsystem (attribute_view_render.go:394, attribute_view_new_item paths). Unlike ErrTreeNotFound (which also fires on non-matching ID patterns in tree loading), ErrInvalidID specifically flags an ID that does not meet the expected format/length constraints for AV operations.
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 251596fc0d)
Solutions
- Validate the ID with ast.IsNodeIDPattern (20-char node ID) before calling AV/tree operations.
- Return ErrInvalidID early from your own input validation rather than letting the kernel reject it deep in the AV stack.
- Use errors.Is(err, model.ErrInvalidID) to give a precise 'malformed ID' message vs generic not-found.
- Ensure IDs originate from SiYuan-generated block IDs, not hand-crafted strings.
Example fix
// before — pass unchecked id to AV
av.AddRow(keyID, ...)
// returns ErrInvalidID
// after — validate first
if !ast.IsNodeIDPattern(keyID) || keyID == "" {
return ErrInvalidID
} Defensive patterns
Strategy: type-guard
Validate before calling
import "github.com/88250/lute/ast"
func isValidNodeID(id string) bool {
return id != "" && ast.IsNodeIDPattern(id)
} Type guard
func isAcceptableAVID(id string) bool {
return id != "" && ast.IsNodeIDPattern(id)
} Try / catch
err := avOp(id)
if errors.Is(err, model.ErrInvalidID) {
return fmt.Errorf("id [%s] is malformed; expected a 20-char node ID", id)
} Prevention
- Validate IDs with ast.IsNodeIDPattern before passing to AV operations.
- Source IDs only from SiYuan-generated block IDs, never hand-crafted strings.
- Use errors.Is(err, model.ErrInvalidID) to give precise input errors.
When it happens
Trigger: An Attribute View operation (render, new item, filter/sort binding) receives an ID that fails the validity check — wrong length, non-hex, empty, or containing illegal characters; a block-ref/AV key binding with a malformed target ID. attribute_view_render.go returns it at lines 394/1036/1072/1113/1178.
Common situations: A plugin or API client passes a truncated/typo'd block ID to an AV endpoint; an imported AV references invalid IDs; manually constructed AV payloads with fabricated IDs that do not match the node-ID pattern; empty string where an ID is required.
Related errors
- invalid attribute view id
- invalid box id
- wrong layout type
- invalid column align
- filter nesting depth exceeds the maximum allowed
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/18fcb60917735226.
Report an issue: GitHub.