knadh/listmonk · error
error compiling transactional template: %v
Error message
error compiling transactional template: %v
What it means
This error is returned by Template.Compile in models/templates.go when the template's Body fails to parse as a Go html/template. Compile is invoked whenever a (transactional) template is created or updated (CreateTemplate, UpdateTemplate), previewed (previewTemplate), or cached (CacheTpl). The wrapped %v is the underlying template parse error (bad syntax, unclosed actions, undefined functions registered in the FuncMap).
Source
Thrown at models/templates.go:43
// Subject is only for type=tx.
Subject string `db:"subject" json:"subject"`
Type string `db:"type" json:"type"`
Body string `db:"body" json:"body,omitempty"`
BodySource null.String `db:"body_source" json:"body_source,omitempty"`
IsDefault bool `db:"is_default" json:"is_default"`
// Only relevant to tx (transactional) templates.
SubjectTpl *txttpl.Template `json:"-"`
Tpl *template.Template `json:"-"`
Attachments []Attachment `json:"-"`
}
// Compile compiles a template body and subject (only for tx templates) and
// caches the templat references to be executed later.
func (t *Template) Compile(f template.FuncMap) error {
tpl, err := template.New(BaseTpl).Funcs(f).Parse(t.Body)
if err != nil {
return fmt.Errorf("error compiling transactional template: %v", err)
}
t.Tpl = tpl
// If the subject line has a template string, compile it.
if hasTplExpr(t.Subject) {
subj := t.Subject
subjTpl, err := txttpl.New(BaseTpl).Funcs(txttpl.FuncMap(f)).Parse(subj)
if err != nil {
return fmt.Errorf("error compiling subject: %v", err)
}
t.SubjectTpl = subjTpl
}
return nil
}
type CampaignStats struct {View on GitHub (pinned to 670c01717d)
Solutions
- Read the wrapped parse error and fix the offending line in Template.Body — usually an unclosed {{ }}, missing {{ end }}, or stray brace.
- Escape any literal {{ or }} in content (e.g. in CSS/JS snippets) as "{{" "}}" or restructure so the parser does not treat them as actions.
- Verify all functions used in the body exist in the FuncMap passed to Compile; register missing ones before CreateTemplate/UpdateTemplate.
- If migrating from another templating engine, convert its syntax (e.g. Jinja {% if %}, Liquid {% for %}) to Go template equivalents ({{ if }}, {{ range }}).
- Re-test by calling previewTemplate with sample data once the body parses.
Example fix
// before
body := "Hi {{ .Subscriber.Name }, you have {{ range .Tx.Items }}item{{ end"
// after
body := "Hi {{ .Subscriber.Name }}, you have {{ range .Tx.Items }}item{{ end }}" Defensive patterns
Strategy: validation
Validate before calling
import "html/template"
func validateTemplateBody(body string, funcs template.FuncMap) error {
_, err := template.New("body").Funcs(funcs).Parse(body)
return err
}
// Call before POST/PUT to the templates API; if it returns an error, fix the body first. Try / catch
if err := tpl.Compile(funcs); err != nil {
if strings.HasPrefix(err.Error(), "error compiling transactional template") {
return fmt.Errorf("template body is not valid Go template syntax: %w", err)
}
return err
} Prevention
- Validate the body with html/template.Parse server-side before saving (exactly what Compile does).
- Escape literal {{ }} appearing in CSS/JS content as {{"{{"}} / {{"}}"}}.
- Convert syntax from other engines (Jinja/Liquid) before pasting into the template editor.
- Keep the template FuncMap stable; document and deprecate functions instead of removing them.
- Use previewTemplate with sample data as part of the save workflow to catch breakage early.
When it happens
Trigger: Calling CreateTemplate/UpdateTemplate with a template whose Body contains invalid html/template syntax — unclosed {{ if }}/{{ range }} blocks, stray {{ or }} characters in content, an unknown function in a pipeline not present in the FuncMap f, or malformed {{ define }}/{{ block }} structures.
Common situations: Users paste HTML with literal curly braces (CSS, JS snippets like `{{ x }}` in code samples) that the parser interprets as template actions; copy-pasting templates from other engines (Jinja2/Liquid) with incompatible syntax; a template function was removed or renamed so pipelines referencing it fail at parse-registered-func lookup; unbalanced tags after hand edits in the admin UI.
Related errors
- error compiling alt body: %v
- error compiling subject: %v
- error compiling subject: %v
- 'email' column not found
- token was not found or has expired
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/a8dd663f813a11d8.
Report an issue: GitHub.