gohugoio/hugo · error
template: %q is an incomplete or empty template
Error message
template: %q is an incomplete or empty template
What it means
Thrown by escape() (invoked by Execute and Prepare) when escapeErr is nil but t.Tree is nil, i.e. the template object exists in the set but was never given a parsed body. html/template cannot escape an absent parse tree, so it refuses to execute. The %q is the template's Name().
Source
Thrown at tpl/internal/go_templates/htmltemplate/template.go:103
if t == nil {
return nil
}
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
if t.nameSpace.escaped {
return fmt.Errorf("html/template: cannot Parse after Execute")
}
return nil
}
// escape escapes all associated templates.
func (t *Template) escape() error {
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
t.nameSpace.escaped = true
if t.escapeErr == nil {
if t.Tree == nil {
return fmt.Errorf("template: %q is an incomplete or empty template", t.Name())
}
if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
return err
}
} else if t.escapeErr != escapeOK {
return t.escapeErr
}
return nil
}
// Execute applies a parsed template to the specified data object,
// writing the output to wr.
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel, although if parallel
// executions share a Writer the output may be interleaved.
func (t *Template) Execute(wr io.Writer, data any) error {View on GitHub (pinned to 52c9bd7908)
Solutions
- Ensure Parse (or ParseFiles/ParseGlob/ParseFS) is called with non-empty content for the template before Execute.
- Check the error return from Parse; a nil Tree is often the residue of a swallowed parse error.
- Verify the template name in Execute matches a template that actually received a parsed body.
- Use Lookup(name).Tree != nil as a sanity check before executing.
Example fix
// before
t := template.New("page")
err := t.Execute(w, data) // error: incomplete/empty
// after
t := template.New("page")
_, err := t.Parse(bodyHTML)
if err != nil { return err }
err = t.Execute(w, data) Defensive patterns
Strategy: validation
Validate before calling
func safeExecute(t *template.Template, w io.Writer, data any) error {
if t == nil || t.Tree == nil {
return fmt.Errorf("template %q has no parsed body", t.Name())
}
return t.Execute(w, data)
} Try / catch
if err := t.Execute(w, data); err != nil {
if strings.Contains(err.Error(), "incomplete or empty template") {
// ensure Parse ran; re-parse from source and retry once
if _, perr := t.Parse(bodySrc); perr != nil { return perr }
err = t.Execute(w, data)
}
if err != nil { return err }
} Prevention
- Always check Parse's error return; a nil Tree often stems from a swallowed parse error.
- After New(name), always follow with a Parse before Execute.
- Log DefinedTemplates() at startup to confirm every name has a body.
When it happens
Trigger: Calling Execute on a Template created via New(name) (or added to a set via t.New) without ever calling Parse/ParseFiles/etc. on it; a template that was registered under a name but whose body parse failed silently.
Common situations: Forgetting to parse after New; referencing a template name that was reserved via {{define}} in another file but whose definition was empty or removed; a parse error earlier leaving Tree nil but the template in the set.
Related errors
- html/template: cannot Parse after Execute
- html/template: %q is an incomplete template
- html/template: cannot Clone %q after it has executed
- html/template: %q is undefined
- html/template: cannot Clone %q after it has executed
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/49ec9d89df69c70a.
Report an issue: GitHub.