gohugoio/hugo · error
failed to transform template
Error message
failed to transform template %q: %w
What it means
applyTemplateTransformers (templatetransform.go:71-91) runs an AST transformation pass over each parsed template to inject partial-return wrappers, deferred nodes, and partial-decorator handling. If applyTransformationsAndSetReturnWrapper returns an error, it is wrapped with the template name. This is a build-time parse/transform failure on a specific template.
Solutions
- Read the wrapped (%w) error to find the specific transformation that failed.
- Inspect the named template for unsupported constructs (e.g. {{ inner }} inside a with-partial, bad $_hugo_config).
- Simplify the template to isolate which construct triggers the transform failure.
- Update Hugo; transform logic is frequently patched.
Defensive patterns
Strategy: try-catch
Try / catch
// In Go tests/builds, unwrap to find the specific sub-transform failure:
if err != nil && strings.Contains(err.Error(), "failed to transform template") {
// the %w holds the real cause (e.g. $_hugo_config decode, inner-in-with)
log.Fatalf("transform failed for template: %v", err)
} Prevention
- Always inspect the wrapped cause, not just the outer template name.
- Validate $_hugo_config and avoid 'inner' inside with-partial blocks.
- Simplify templates when diagnosing transform errors.
When it happens
Trigger: A template whose parsed AST cannot be transformed — typically because a nested transformation (config decode, partial decorator creation, inner-insertion) failed. The wrapped error identifies the specific sub-failure; the outer message identifies which template it happened in.
Common situations: A malformed $_hugo_config header; a {{ with }} block wrapping a partial decorator that contains an unsupported construct; syntax that parses but is semantically invalid during the transform pass; Hugo version regression in the transformer.
Related errors
- failed to add internal partial decorator template
- failed to create internal partial decorator template
- failed to decode $_hugo_config in template
- failed to transform internal partial decorator template
- inner cannot be used inside a with block that wraps a…
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/a7b97b2e2f2b1e2b.
Report an issue: GitHub.
Appendix: source
Thrown at tpl/tplimpl/templatetransform.go:88
func applyTemplateTransformers(
t *TemplInfo,
store *TemplateStore,
lookupFn func(name string, in *TemplInfo) *TemplInfo,
) (*templateTransformContext, error) {
if t == nil {
return nil, errors.New("expected template, but none provided")
}
c := newTemplateTransformContext(t, store, lookupFn)
c.t.ParseInfo = defaultParseInfo
tree := getParseTree(t.Template)
if tree == nil {
panic(fmt.Errorf("template %s not parsed", t))
}
if err := c.applyTransformationsAndSetReturnWrapper(tree); err != nil {
return c, fmt.Errorf("failed to transform template %q: %w", t.Name(), err)
}
return c, c.err
}
func getParseTree(templ tpl.Template) *parse.Tree {
if text, ok := templ.(*texttemplate.Template); ok {
return text.Tree
}
return templ.(*htmltemplate.Template).Tree
}
const (
// We parse this template and modify the nodes in order to assign
// the return value of a partial to a contextWrapper via Set. We use
// "range" over a one-element slice so we can shift dot to the
// partial's argument, Arg, while allowing Arg to be falsy.
partialReturnWrapperTempl = `{{ $_hugo_dot := $ }}{{ $ := .Arg }}{{ range (slice .Arg) }}{{ $_hugo_dot.Set ("PLACEHOLDER") }}{{ end }}`View on GitHub (pinned to 52c9bd7908)