{"record":{"id":"ceb5b50844af0fac","repo":"knadh/listmonk","slug":"error-rendering-header-q-v","errorCode":null,"errorMessage":"error rendering header %q: %v","messagePattern":"error rendering header %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/manager/message.go","lineNumber":80,"sourceCode":"\t}\n\n\t// If there are templated headers, compile them.\n\tif m.Campaign.HeaderTpls == nil {\n\t\tm.headers = m.Campaign.Headers\n\t} else {\n\t\thdrOut := bytes.Buffer{}\n\t\tm.headers = make(models.Headers, len(m.Campaign.Headers))\n\t\tfor i, set := range m.Campaign.Headers {\n\t\t\tm.headers[i] = make(map[string]string, len(set))\n\t\t\tfor hdr, val := range set {\n\t\t\t\ttpl := m.Campaign.HeaderTpls[i][hdr]\n\t\t\t\tif tpl == nil {\n\t\t\t\t\tm.headers[i][hdr] = val\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\thdrOut.Reset()\n\t\t\t\tif err := tpl.ExecuteTemplate(&hdrOut, models.ContentTpl, m); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error rendering header %q: %v\", hdr, err)\n\t\t\t\t}\n\t\t\t\tm.headers[i][hdr] = hdrOut.String()\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Subject returns a copy of the message subject\nfunc (m *CampaignMessage) Subject() string {\n\treturn m.subject\n}\n\n// Body returns a copy of the message body.\nfunc (m *CampaignMessage) Body() []byte {\n\tout := make([]byte, len(m.body))\n\tcopy(out, m.body)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/knadh/listmonk/blob/670c01717d48647093335cc23a6be6f4b79c3b6b/internal/manager/message.go#L62-L98","documentation":"Campaign message headers may themselves be templates (e.g. 'X-Campaign: {{ .Name }}'). During render, each templated header value is executed with the campaign as data; if template execution fails (bad template syntax, unknown function/field, wrong data type), this wrapped error names the offending header and the underlying template error.","triggerScenarios":"Defining a campaign header value containing invalid Go template syntax ({{ .Nonexistent.Depth }}), calling an undefined template function, or a field type mismatch in the header expression while NewCampaignMessage renders the message.","commonSituations":"Typos in header template expressions like {{ .CampagnName }}, custom template funcs not registered in the manager, copy-pasted header templates from examples with unsupported fields, or whitespace/pipe errors in the template.","solutions":["Fix the header template expression — verify every field exists on the campaign model (e.g. {{ .Name }}, {{ .ID }})","Test the template locally with template.Template.ExecuteTemplate against a sample campaign struct","Register any custom template functions used in headers via the manager's template func map","Simplify or remove the templating from the header if it's static content"],"exampleFix":"// before\n\"X-Campaign\": \"{{ .CampagnName }}\" // typo -> can't evaluate field\n// after\n\"X-Campaign\": \"{{ .Name }}\"","handlingStrategy":"try-catch","validationCode":"// Validate header templates at config/campaign-save time\nfor _, v := range headers {\n    t, err := template.New(\"hdr\").Funcs(funcMap).Parse(v)\n    if err != nil { return fmt.Errorf(\"bad header template %q: %v\", v, err) }\n    if err := t.Execute(io.Discard, sampleCampaign); err != nil { return err }\n}","typeGuard":null,"tryCatchPattern":"if err := renderHeaders(m); err != nil {\n    var hdr string\n    if matches := hdrErrRe.FindStringSubmatch(err.Error()); matches != nil {\n        hdr = matches[1] // header name from 'error rendering header %q'\n    }\n    return fmt.Errorf(\"fix templated header %q: %w\", hdr, err)\n}","preventionTips":["Pre-validate header templates with a sample campaign at campaign save time","Only reference fields that exist on the campaign model (Name, ID, etc.)","Register every custom template function used in headers in the manager's func map","Keep header templates simple; avoid nested/typed field access in header expressions"],"tags":["template","headers","rendering","go-template"],"backgroundTag":"template-render-failed","analyzedSha":"670c01717d48647093335cc23a6be6f4b79c3b6b","analyzedAt":"2026-09-01T03:39:35.452Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}