gohugoio/hugo · error

failed to execute template

Error message

failed to execute template %s: %w

What it means

Returned by pageContentOutput.Render (page__per_output.go:123) when the resolved layout template exists but failed during execution. The template was located successfully but executeToString raised a runtime error while rendering it against the page; that error is wrapped with the template's Name().

Solutions

  1. Read the wrapped error — it identifies the template name and the runtime cause; fix the offending expression in that layout.
  2. Run `hugo --templateMetricsHints` and check the named template for nil/unsafe access; add `with`/`if` guards.
  3. Reproduce with a minimal content file and use `hugo server --disableFastRender` to get a full stack.

Example fix

{{/* before: .Author may be nil */}}
{{ .Author.Name }}

{{/* after */}}
{{ with .Author }}{{ .Name }}{{ end }}
Defensive patterns

Strategy: try-catch

Type guard

{{/* Guard against nil fields that commonly cause execution errors */}}
{{ with .Author }}{{ .Name }}{{ end }}
{{ with .Params.cover }}{{ .url }}{{ end }}

Try / catch

{{/* Wrap .Render so failures degrade gracefully in dev */}}
{{ $html := "" }}
{{ with .Render "mylayout" }}{{ $html = . }}{{ else }}
  {{ warnf "layout 'mylayout' failed for %s" .File.Path }}
{{ end }}

Prevention

When it happens

Trigger: The layout references an undefined method or field on the page object; calls a template func with wrong argument count/types; divides by zero; accesses nil in a way the Go template engine rejects; a partial invoked from the layout errors.

Common situations: Refactoring page methods and forgetting to update layouts; a content adapter page missing fields a normal page has; partial template bugs that only surface for certain content shapes; version upgrades where a method signature changed.

Related errors


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

Appendix: source

Thrown at hugolib/page__per_output.go:123

}

func (pco *pageContentOutput) Render(ctx context.Context, layout ...string) (template.HTML, error) {
	if len(layout) == 0 {
		return "", errors.New("no layout given")
	}
	templ, found, err := pco.po.p.resolveTemplate(layout...)
	if err != nil {
		return "", pco.po.p.wrapError(err)
	}

	if !found {
		return "", fmt.Errorf("template %q not found", layout[0])
	}

	// Make sure to send the *pageState and not the *pageContentOutput to the template.
	res, err := executeToString(ctx, pco.po.p.s.GetTemplateStore(), templ, pco.po.p)
	if err != nil {
		return "", pco.po.p.wrapError(fmt.Errorf("failed to execute template %s: %w", templ.Name(), err))
	}
	return template.HTML(res), nil
}

func (pco *pageContentOutput) Fragments(ctx context.Context) *tableofcontents.Fragments {
	return pco.c().Fragments(ctx)
}

func (pco *pageContentOutput) RenderShortcodes(ctx context.Context) (template.HTML, error) {
	return pco.c().RenderShortcodes(ctx)
}

func (pco *pageContentOutput) Markup(opts ...any) page.Markup {
	if len(opts) > 1 {
		panic("too many arguments, expected 0 or 1")
	}
	var scope string
	if len(opts) == 1 {

View on GitHub (pinned to 52c9bd7908)