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

  1. Read the wrapped parse error and fix the offending line in Template.Body — usually an unclosed {{ }}, missing {{ end }}, or stray brace.
  2. Escape any literal {{ or }} in content (e.g. in CSS/JS snippets) as "{{" "}}" or restructure so the parser does not treat them as actions.
  3. Verify all functions used in the body exist in the FuncMap passed to Compile; register missing ones before CreateTemplate/UpdateTemplate.
  4. If migrating from another templating engine, convert its syntax (e.g. Jinja {% if %}, Liquid {% for %}) to Go template equivalents ({{ if }}, {{ range }}).
  5. 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

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


AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01). Data as JSON: /api/errors/a8dd663f813a11d8. Report an issue: GitHub.