{"record":{"id":"7b3442345ee0aa88","repo":"siyuan-note/siyuan","slug":"parse-template-s-failed-s","errorCode":null,"errorMessage":"parse template [%s] failed: %s","messagePattern":"parse template \\[(.+?)\\] failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/av/calc_template.go","lineNumber":92,"sourceCode":"\t\tctx[\"min\"] = float64(0)\n\t\tctx[\"max\"] = float64(0)\n\t\tctx[\"median\"] = float64(0)\n\t}\n\treturn ctx\n}\n\n// evalRollupTemplate 使用 text/template + sprig 渲染自定义模板统计内容。\n// 返回渲染后的字符串；若该字符串可解析为数字则 isNumber 为 true 且 asNumber 为该数值。\n// 解析或执行失败时返回 err，由调用方决定如何提示用户。\nfunc evalRollupTemplate(templateContent string, ctx map[string]any) (rendered string, asNumber float64, isNumber bool, err error) {\n\tif \"\" == templateContent {\n\t\treturn\n\t}\n\n\tgoTpl := template.New(\"\").Delims(\".action{\", \"}\").Funcs(templateFuncMap())\n\ttpl, parseErr := goTpl.Parse(templateContent)\n\tif nil != parseErr {\n\t\terr = fmt.Errorf(\"parse template [%s] failed: %s\", templateContent, parseErr)\n\t\treturn\n\t}\n\n\tbuf := &bytes.Buffer{}\n\tif execErr := tpl.Execute(buf, ctx); nil != execErr {\n\t\terr = fmt.Errorf(\"execute template [%s] failed: %s\", templateContent, execErr)\n\t\treturn\n\t}\n\n\trendered = buf.String()\n\tif \"<no value>\" == rendered {\n\t\trendered = \"\"\n\t\treturn\n\t}\n\n\t// 渲染结果若可解析为数字，则按数字处理（前端会按列数字格式显示）\n\ttrimmed := strings.TrimSpace(rendered)\n\tif \"\" != trimmed {","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/av/calc_template.go#L74-L110","documentation":"Formatted error raised in evalRollupTemplate when Go text/template parsing of a rollup template (delims .action{ }) fails. The message embeds the offending template content and the underlying parse error, so a syntax error in the template body is directly visible.","triggerScenarios":"calcFieldRollup/calcFieldByTemplate evaluating a rollup whose template content contains invalid template syntax — unbalanced .action{ }, wrong pipe/field syntax, or characters that break the Go template lexer.","commonSituations":"User-typed template with a typo like .action{.value} vs .action{.value}; missing closing brace after editing; copying a template from docs where the delimiter got mangled; programmatic generation interpolating raw text containing \"}\".","solutions":["Fix the template syntax shown in the message — check every .action{ has a matching }","Test the template in the SiYuan template editor before saving the rollup","Escape or strip stray braces from programmatically generated template content"],"exampleFix":"// before\ntpl := \".action{.foo }{.bar}\" // unbalanced\n// after\ntpl := \".action{.foo}.action{.bar}\" // balanced delimiters","handlingStrategy":"try-catch","validationCode":"_, perr := template.New(\"\").Delims(\".action{\", \"}\").Parse(tplContent)\nif perr != nil {\n    return fmt.Errorf(\"template syntax invalid: %v\", perr)\n}","typeGuard":null,"tryCatchPattern":"if _, err := evalRollupTemplate(tplContent, ctx); err != nil {\n    if strings.HasPrefix(err.Error(), \"parse template\") {\n        // show err to user: it embeds the bad template and parse reason\n    }\n}","preventionTips":["Verify every .action{ has a closing }","Escape stray braces in generated content","Test templates in the editor before saving rollups"],"tags":["template","rollup","attribute-view"],"backgroundTag":"invalid-template-syntax","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}