gohugoio/hugo · error

html/template: %q is undefined

Error message

html/template: %q is undefined

What it means

Returned by lookupAndEscapeTemplate (used by ExecuteTemplate) when no template with the given name exists in the set (t.set[name] == nil). html/template requires the target template to be associated with the caller before it can be executed. The %q is the requested name.

Source

Thrown at tpl/internal/go_templates/htmltemplate/template.go:152

// executions share a Writer the output may be interleaved.
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data any) error {
	tmpl, err := t.lookupAndEscapeTemplate(name)
	if err != nil {
		return err
	}
	return tmpl.text.Execute(wr, data)
}

// lookupAndEscapeTemplate guarantees that the template with the given name
// is escaped, or returns an error if it cannot be. It returns the named
// template.
func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
	t.nameSpace.mu.Lock()
	defer t.nameSpace.mu.Unlock()
	t.nameSpace.escaped = true
	tmpl = t.set[name]
	if tmpl == nil {
		return nil, fmt.Errorf("html/template: %q is undefined", name)
	}
	if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK {
		return nil, tmpl.escapeErr
	}
	if tmpl.text.Tree == nil || tmpl.text.Root == nil {
		return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
	}
	if t.text.Lookup(name) == nil {
		panic("html/template internal error: template escaping out of sync")
	}
	if tmpl.escapeErr == nil {
		err = escapeTemplate(tmpl, tmpl.text.Root, name)
	}
	return tmpl, err
}

// DefinedTemplates returns a string listing the defined templates,
// prefixed by the string "; defined templates are: ". If there are none,

View on GitHub (pinned to 52c9bd7908)

Solutions

  1. Verify the exact name passed to ExecuteTemplate matches a {{define}} name or a parsed file's base name in the same set.
  2. Call t.Lookup(name) before ExecuteTemplate and fail with a clear message if nil.
  3. Ensure all partials are parsed into the same template set (associate via t.Parse of shared definitions or t.New).
  4. List defined templates via t.Templates() / t.DefinedTemplates() to confirm available names.

Example fix

// before
err := t.ExecuteTemplate(w, "page", data) // error: "page" undefined

// after
if t.Lookup("page") == nil {
    return fmt.Errorf("page not in set; have: %s", t.DefinedTemplates())
}
err := t.ExecuteTemplate(w, "page", data)
Defensive patterns

Strategy: validation

Validate before calling

func executeNamed(t *template.Template, name string, w io.Writer, data any) error {
    if t.Lookup(name) == nil {
        return fmt.Errorf("template %q undefined; available:%s", name, t.DefinedTemplates())
    }
    return t.ExecuteTemplate(w, name, data)
}

Try / catch

if err := t.ExecuteTemplate(w, name, data); err != nil {
    if strings.Contains(err.Error(), "is undefined") {
        // fall back to a known default template
        return t.ExecuteTemplate(w, defaultName, data)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ExecuteTemplate(w, name, data) where name does not match any template registered in the same association set (never defined, typo, or defined in a different template set).

Common situations: Typo in the layout/partial name; referencing a partial that lives in a different template set; using a base name vs full path mismatch; templates parsed into separate New() sets rather than one associated set.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/55ddddf3b80857b8. Report an issue: GitHub.