siyuan-note/siyuan · warning

execute template [%s] failed: %s

Error message

execute template [%s] failed: %s

What it means

Thrown by evalRollupTemplate when text/template parsed the string successfully but Execute failed against the data context. Execution failures are runtime: wrong argument types/counts to a sprig function, indexing into a missing key, or calling a removed function. The error is surfaced to the user as a 30-second toast via pushRollupTemplateErr (calc_template.go:178).

Source

Thrown at kernel/av/calc_template.go:98

// evalRollupTemplate 使用 text/template + sprig 渲染自定义模板统计内容。
// 返回渲染后的字符串;若该字符串可解析为数字则 isNumber 为 true 且 asNumber 为该数值。
// 解析或执行失败时返回 err,由调用方决定如何提示用户。
func evalRollupTemplate(templateContent string, ctx map[string]any) (rendered string, asNumber float64, isNumber bool, err error) {
	if "" == templateContent {
		return
	}

	goTpl := template.New("").Delims(".action{", "}").Funcs(templateFuncMap())
	tpl, parseErr := goTpl.Parse(templateContent)
	if nil != parseErr {
		err = fmt.Errorf("parse template [%s] failed: %s", templateContent, parseErr)
		return
	}

	buf := &bytes.Buffer{}
	if execErr := tpl.Execute(buf, ctx); nil != execErr {
		err = fmt.Errorf("execute template [%s] failed: %s", templateContent, execErr)
		return
	}

	rendered = buf.String()
	if "<no value>" == rendered {
		rendered = ""
		return
	}

	// 渲染结果若可解析为数字,则按数字处理(前端会按列数字格式显示)
	trimmed := strings.TrimSpace(rendered)
	if "" != trimmed {
		if num, parseErr := strconv.ParseFloat(trimmed, 64); nil == parseErr {
			asNumber = num
			isNumber = true
		}
	}
	return

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Use only the documented context keys: values, strings, raw, count, sum, avg, min, max, median, nonEmptyCount (buildRollupTemplateContext, calc_template.go:35-78).
  2. Avoid env, expandenv, getHostByName — they were removed; use static values instead.
  3. Test arithmetic expressions in isolation (e.g. .action{ add .sum 1 }) to confirm sprig function signatures.

Example fix

// before
calc.Template = ".action{ .average }"
// after
calc.Template = ".action{ .avg }"
Defensive patterns

Strategy: try-catch

Try / catch

// Execution errors are runtime; catch them at the calc site and degrade gracefully.
rendered, asNumber, isNumber, err := evalRollupTemplate(calc.Template, ctx)
if err != nil {
    pushRollupTemplateErr(err) // toast + leave calc.Result empty
    return
}
// use rendered / asNumber / isNumber

Prevention

When it happens

Trigger: Template references a context key that does not exist (e.g. .average instead of .avg), invokes a sprig function with the wrong arity, or calls env/expandenv/getHostByName which were deleted for security. Fires during column calc rendering in calc.go:2003 and calcFieldByTemplate in calc_template.go:164.

Common situations: Misremembering the exposed context keys; copy-pasting a sprig recipe that needs args differently; version skew after the security removal of env-like funcs (GHSA-v97v-gxxg-rhmq).

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/145b092dd49d3370. Report an issue: GitHub.