{"record":{"id":"e3251d03e7ec6e6b","repo":"siyuan-note/siyuan","slug":"parse-tree-s-failed-e3251d","errorCode":null,"errorMessage":"parse tree [%s] failed","messagePattern":"parse tree \\[(.+?)\\] failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template.go","lineNumber":425,"sourceCode":"\tgoTpl = goTpl.Funcs(tplFuncMap)\n\ttpl, err := goTpl.Funcs(tplFuncMap).Parse(gulu.Str.FromBytes(md))\n\tif err != nil {\n\t\terr = fmt.Errorf(Conf.Language(44), err.Error())\n\t\treturn\n\t}\n\n\tbuf := &bytes.Buffer{}\n\tbuf.Grow(4096)\n\tif err = tpl.Execute(buf, dataModel); err != nil {\n\t\terr = fmt.Errorf(Conf.Language(44), err.Error())\n\t\treturn\n\t}\n\tmd = buf.Bytes()\n\ttree = parseKTree(md)\n\tif nil == tree {\n\t\tmsg := fmt.Sprintf(\"parse tree [%s] failed\", p)\n\t\tlogging.LogError(msg)\n\t\terr = errors.New(msg)\n\t\treturn\n\t}\n\n\tvar nodesNeedAppendChild, unlinks []*ast.Node\n\t// 模板内部块旧 ID 到新 ID 的映射，用于成套改写模板内部的自引用\n\tblockIDs := map[string]string{}\n\tast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {\n\t\tif !entering {\n\t\t\treturn ast.WalkContinue\n\t\t}\n\n\t\tif \"\" != n.ID {\n\t\t\t// 重新生成 ID，并记录旧 ID 到新 ID 的映射，用于后续成套改写模板内部的自引用\n\t\t\toldID := n.ID\n\t\t\tn.ID = ast.NewNodeID()\n\t\t\tblockIDs[oldID] = n.ID\n\t\t\tn.SetIALAttr(\"id\", n.ID)\n\t\t\tn.RemoveIALAttr(av.NodeAttrNameAvs)","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/template.go#L407-L443","documentation":"Thrown by model.RenderTemplate (kernel/model/template.go:374) after a template file is read, executed as a Go text/template with delims .action{ } against the block's data model, and the rendered bytes are handed to parseKTree (Lute kramdown). If Lute returns a nil tree, the rendered output is not valid SiYuan kramdown markdown, and the error embeds the template file path p. Note this is distinct from the Conf.Language(44) errors raised one step earlier for template parse/execute failures - this error means execution succeeded but the output is unparseable.","triggerScenarios":"Calling /api/template/render (or creating/updating a doc whose template renders through RenderTemplate) with a template body that expands to text Lute cannot parse: unclosed code fences, stray or malformed kramdown IAL syntax like {: id=..., .action{...} constructs that emit raw HTML or garbage, or a template that renders to empty/whitespace-only output.","commonSituations":"Hand-edited templates in data/templates; templates copied from the web containing non-kramdown syntax; SQL template funcs (sql.SQLTemplateFuncs) emitting unexpected values; a loop/condition that swallows all content leaving nothing parseable.","solutions":["Open the template file at the path shown in the error and inspect what it renders to, bisecting by temporarily replacing .action{...} constructs with plain text","Fix or remove malformed kramdown block IAL remnants ({: ...}) and unclosed code fences/table rows in the template","Ensure the template renders to at least one valid block (heading, paragraph, list) and is not empty for the given block's data model","Dry-run the same template via /api/template/render on a known-good block id until it parses, then reuse it for doc creation"],"exampleFix":"// data/templates/report.md (before) - emits a broken, unclosed IAL\n.action{.title}{: id=\"broken\n\n// after - plain valid kramdown\n# .action{.title}","handlingStrategy":"try-catch","validationCode":"// Dry-run the template on a known-good block before relying on it:\n// POST /api/template/render  {\"id\": \"<known block id>\", \"path\": \"data/templates/my.md\"}\n// A 200 response with a DOM means the rendered output parses; only then use it for doc creation.","typeGuard":null,"tryCatchPattern":"// Go caller\nif _, _, err := model.RenderTemplate(p, id, false); err != nil {\n\tif strings.Contains(err.Error(), \"parse tree [\") {\n\t\t// template content problem - fix the template file at the reported path\n\t}\n}","preventionTips":["Keep templates as plain kramdown markdown; avoid emitting raw IAL syntax ({: ...}) from .action{} constructs","Re-run /api/template/render after every template edit before using it in automation","Ensure templates always render at least one valid block for any data model"],"tags":["template","markdown","lute","kramdown","parse"],"backgroundTag":"markdown-parse-error","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}