{"record":{"id":"befc4e4b5f8c4024","repo":"siyuan-note/siyuan","slug":"found-invalid-id-s","errorCode":null,"errorMessage":"found invalid ID [%s]","messagePattern":"found invalid ID \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/block_update.go","lineNumber":198,"sourceCode":"\t\tblankParagraph := treenode.NewParagraph(\"\")\n\t\tret = luteEngine.RenderNodeBlockDOM(blankParagraph)\n\t}\n\n\tinvalidID := \"\"\n\tif nil != tree && nil != tree.Root {\n\t\tast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {\n\t\t\tif !entering {\n\t\t\t\treturn ast.WalkContinue\n\t\t\t}\n\t\t\tif \"\" != n.ID && !ast.IsNodeIDPattern(n.ID) {\n\t\t\t\tinvalidID = n.ID\n\t\t\t\treturn ast.WalkStop\n\t\t\t}\n\t\t\treturn ast.WalkContinue\n\t\t})\n\t}\n\tif \"\" != invalidID {\n\t\treturn \"\", errors.New(\"found invalid ID [\" + invalidID + \"]\")\n\t}\n\treturn\n}\n\nfunc parseBlockUpdateData(data, dataType string, luteEngine *lute.Lute) (ret string, tree *parse.Tree, err error) {\n\tret = data\n\tswitch dataType {\n\tcase \"markdown\":\n\t\tret, err = DataBlockDOM(data, luteEngine)\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"data block DOM failed: %w\", err)\n\t\t\treturn\n\t\t}\n\tcase \"dom\":\n\tdefault:\n\t\terr = fmt.Errorf(\"unsupported block data type [%s]\", dataType)\n\t\treturn\n\t}","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/block_update.go#L180-L216","documentation":"Returned by the post-normalization validation pass in the block-update pipeline. After building the new subtree, ast.Walk scans every node; any node whose ID is non-empty but fails ast.IsNodeIDPattern sets invalidID and the function returns 'found invalid ID [<id>]'. This catches malformed IDs in user-supplied input data (markdown/dom) before they are committed.","triggerScenarios":"User-supplied markdown contains a kramdown block IAL with a hand-written malformed ID; DOM input embeds a non-SiYuan ID; an integration synthesizes IDs with the wrong format.","commonSituations":"Hand-authored markdown with {...} attributes using arbitrary strings; pasted content from another system that preserves foreign IDs; Lute producing an unexpected ID shape from exotic syntax.","solutions":["Strip or regenerate block IDs in the input before submitting (let Lute mint fresh IDs).","Validate every {...} IAL ID in the markdown against ast.IsNodeIDPattern before the update.","When using dom input, ensure all id= attributes match the SiYuan block ID pattern."],"exampleFix":"// before\n// markdown contains: text{ id=\"abc def\" }\n\n// after\n// regenerate the id with a SiYuan-format id, e.g.\n// text{ id=\"20240101000000abcdef\" }","handlingStrategy":"validation","validationCode":"// scan the input DOM/markdown for IAL ids and validate each\nre := regexp.MustCompile(`\\{[^}]*id=\"([^\"]+)\"`)\nfor _, m := range re.FindAllStringSubmatch(input.Data, -1) {\n    if !ast.IsNodeIDPattern(m[1]) {\n        return fmt.Errorf(\"invalid id in input: %q\", m[1])\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Strip foreign IDs from pasted content before submission.","Let Lute mint fresh IDs rather than hand-writing them.","Validate every {...} IAL id against IsNodeIDPattern in any markdown pipeline."],"tags":["block-update","validation","block-id","lute"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}