{"record":{"id":"18fcb60917735226","repo":"siyuan-note/siyuan","slug":"invalid-id","errorCode":null,"errorMessage":"invalid id","messagePattern":"invalid id","errorType":"error_code","errorClass":"ErrInvalidID","httpStatus":null,"severity":"error","filePath":"kernel/model/tree.go","lineNumber":208,"sourceCode":"\t\t}\n\t}\n\n\tret, err = dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"parse json to tree [%s] failed: %s\", localPath, err)\n\t\treturn\n\t}\n\treturn\n}\n\nvar (\n\tErrBoxNotFound   = errors.New(\"notebook not found\")\n\tErrBoxClosed     = errors.New(\"notebook closed\")\n\tErrBlockNotFound = errors.New(\"block not found\")\n\tErrTreeNotFound  = errors.New(\"tree not found\")\n\tErrIndexing      = errors.New(\"indexing\")\n\tErrBoxUnindexed  = errors.New(\"notebook unindexed\")\n\tErrInvalidID     = errors.New(\"invalid id\")\n)\n\nfunc LoadTreeByBlockIDWithReindex(id string) (ret *parse.Tree, err error) {\n\treturn LoadTreeByBlockIDWithReindexInBox(id, \"\")\n}\n\n// LoadTreeByBlockIDWithReindexInBox 与 LoadTreeByBlockIDWithReindex 一致，但按 boxID 路由 blocktree 查询。\nfunc LoadTreeByBlockIDWithReindexInBox(id, boxID string) (ret *parse.Tree, err error) {\n\tif \"\" == id {\n\t\tlogging.LogWarnf(\"block id is empty\")\n\t\treturn nil, ErrTreeNotFound\n\t}\n\n\tbt := treenode.GetBlockTreeInBox(id, boxID)\n\tif nil == bt && \"\" == boxID {\n\t\t// boxID 未知时（如通用打开入口），遍历所有已打开的加密笔记本查找\n\t\tfor _, encBoxID := range treenode.GetOpenedEncryptedBoxIDs() {\n\t\t\tif encBT := treenode.GetBlockTreeInBox(id, encBoxID); nil != encBT {","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/tree.go#L190-L226","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — pass unchecked id to AV\nav.AddRow(keyID, ...)\n// returns ErrInvalidID\n\n// after — validate first\nif !ast.IsNodeIDPattern(keyID) || keyID == \"\" {\n    return ErrInvalidID\n}","handlingStrategy":"type-guard","validationCode":"import \"github.com/88250/lute/ast\"\n\nfunc isValidNodeID(id string) bool {\n    return id != \"\" && ast.IsNodeIDPattern(id)\n}","typeGuard":"func isAcceptableAVID(id string) bool {\n    return id != \"\" && ast.IsNodeIDPattern(id)\n}","tryCatchPattern":"err := avOp(id)\nif errors.Is(err, model.ErrInvalidID) {\n    return fmt.Errorf(\"id [%s] is malformed; expected a 20-char node ID\", id)\n}","preventionTips":["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."],"tags":["id","validation","sentinel","attribute-view","format"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}