siyuan-note/siyuan · error

Parse template failed

Error message

Parse template failed: %s

What it means

RenderGoTemplateAtInBox (and its wrapper RenderGoTemplateInBox) parse user content with Go text/template using standard {{ }} delimiters; a parse failure returns i18n key 44 ('Parse template failed: %s') carrying Go's parse error text. The func map is filesys.BuiltInTemplateFuncs plus sql.SQLTemplateFuncs and a fixed 'now', so referencing any other function fails at parse time with 'function X not defined'.

Solutions

  1. Fix the syntax error at the offset quoted in Go's parse error
  2. Reference only built-in and SQL template functions, and access data with a leading dot
  3. Dry-run template.New("").Funcs(...).Parse(content) locally before submitting

Example fix

// before
{{title}}
// after
{{.title}}
Defensive patterns

Strategy: validation

Validate before calling

tmpl := template.New("").Funcs(filesys.BuiltInTemplateFuncs())
if _, err := tmpl.Parse(content); err != nil {
	return fmt.Errorf("template rejected at authoring time: %w", err)
}
model.RenderGoTemplateInBox(content, boxID)

Prevention

When it happens

Trigger: Unclosed {{, malformed pipelines, or calling a function that is not in the built-in or SQL func map inside {{...}} when rendering via RenderGoTemplate(At)InBox.

Common situations: Typos like {{.title}; using {{title}} without a leading dot (parsed as a function call); calling helpers that do not exist in the func map.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/3e3558425ba5ad63. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/template.go:75

// RenderGoTemplateAt 使用固定时间渲染 Go 模板,保证同一次业务操作中的多个模板结果一致。
func RenderGoTemplateAt(templateContent string, now time.Time) (ret string, err error) {
	return RenderGoTemplateAtInBox(templateContent, now, "")
}

func RenderGoTemplateInBox(templateContent, boxID string) (ret string, err error) {
	return RenderGoTemplateAtInBox(templateContent, time.Now(), boxID)
}

func RenderGoTemplateAtInBox(templateContent string, now time.Time, boxID string) (ret string, err error) {
	tmpl := template.New("")
	tplFuncMap := filesys.BuiltInTemplateFuncs()
	tplFuncMap["now"] = func() time.Time { return now }
	sql.SQLTemplateFuncs(&tplFuncMap, boxID)
	tmpl = tmpl.Funcs(tplFuncMap)
	tpl, err := tmpl.Parse(templateContent)
	if err != nil {
		return "", fmt.Errorf(Conf.Language(44), err.Error())
	}

	buf := &bytes.Buffer{}
	buf.Grow(4096)
	err = tpl.Execute(buf, nil)
	if err != nil {
		return "", fmt.Errorf(Conf.Language(44), err.Error())
	}
	ret = buf.String()
	return
}

// RemoveTemplate 删除模板文件,路径必须限定在 <data>/templates/ 目录内,防止任意文件被删除
func RemoveTemplate(p string) (err error) {
	abs := p
	if !filepath.IsAbs(abs) {
		abs = filepath.Join(util.DataDir, "templates", p)
	}

View on GitHub (pinned to afa823b6b4)