vxcontrol/pentagi · error

failed to parse template: %w

Error message

failed to parse template: %w

What it means

ExtractTemplateVariables calls parse.Parse("validation", content, "{{", "}}", funcMap) to build the template AST. Any syntax error Go's template parser reports (unclosed action, bad pipeline, unknown character) is wrapped with this message. The funcMap registers builtins as nil so parser-level references to them don't fail.

Source

Thrown at backend/pkg/templates/validator/validator.go:124

	// Create function map with all builtin functions as nil values for the parser
	funcMap := template.FuncMap{
		// Builtin comparison and logic functions
		"and": nil, "or": nil, "not": nil,
		"eq": nil, "ne": nil, "lt": nil, "le": nil, "gt": nil, "ge": nil,
		// Builtin utility functions
		"len": nil, "index": nil, "slice": nil, "print": nil, "printf": nil, "println": nil,
		"html": nil, "js": nil, "urlquery": nil, "call": nil,
		// Additional common functions that might be used
		"add": nil, "sub": nil, "mul": nil, "div": nil, "mod": nil,
		"upper": nil, "lower": nil, "title": nil, "trim": nil, "trimSpace": nil,
		"default": nil, "empty": nil, "contains": nil, "hasPrefix": nil, "hasSuffix": nil,
	}

	// Parse template with function map to get AST
	parsed, err := parse.Parse("validation", templateContent, "{{", "}}", funcMap)
	if err != nil {
		return nil, fmt.Errorf("failed to parse template: %w", err)
	}

	variables := make(map[string]bool)

	// Analyze each tree in the template
	for _, tree := range parsed {
		if tree != nil && tree.Root != nil {
			extractVariablesFromNode(tree.Root, variables, false)
		}
	}

	// Convert to sorted slice for consistent comparison
	var result []string
	for varName := range variables {
		result = append(result, varName)
	}
	sort.Strings(result)

View on GitHub (pinned to ea665308ba)

Solutions

  1. Read the wrapped parse error — it names the template line/position of the syntax problem; fix that action.
  2. Validate the template locally with text/template or http://golang.org/pkg/text/template playground before storing it.
  3. Ensure only Go template syntax is used (no Handlebars/Jinja constructs).
  4. Balance all {{if}}/{{range}}/{{with}} blocks with matching {{end}}.

Example fix

// before
tmpl := "Hello {{ .Name" // missing closing braces
vars, err := validator.ExtractTemplateVariables(tmpl)
// after
tmpl := "Hello {{ .Name }}"
vars, err := validator.ExtractTemplateVariables(tmpl)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := template.New("check").Funcs(funcMap).Parse(tmpl); err != nil {
    return fmt.Errorf("invalid template: %w", err)
}

Type guard

func parseableTemplate(s string) bool {
    _, err := texttemplate.New("t").Parse(s)
    return err == nil
}

Try / catch

vars, err := validator.ExtractTemplateVariables(tmpl)
var parseFailed = strings.Contains(err.Error(), "failed to parse template")
if parseFailed {
    // log err (it names line/offset), return the template to the author for fixing
}

Prevention

When it happens

Trigger: Passing template text with malformed Go template syntax to ExtractTemplateVariables or ValidatePrompt: '{{ .Name' (missing close), '{{if}}' without '{{end}}', invalid function call syntax, stray '}}'.

Common situations: LLM-generated or user-authored prompt templates with typos; mixing Jinja/Handlebars syntax ({{#if}}, {% if %}) with Go templates; edits that dropped an {{end}}.

Understand the failure class

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/ef549a29e21b6b1b. Report an issue: GitHub.