gohugoio/hugo · error
resources.PostProcess cannot be used in a deferred template
Error message
resources.PostProcess cannot be used in a deferred template
What it means
Thrown during template AST transformation when a deferred template (a `with`/partial marked with `defer`) contains a reference to resources.PostProcess (tpl/tplimpl/templatetransform.go:451-453). Hugo forbids PostProcess inside deferred execution because the deferred pass runs after the resources pipeline is already finalized, so deferred PostProcess could never take effect.
Solutions
- Move the resources.PostProcess call out of the deferred template into a non-deferred partial or the base template.
- Remove the `defer` argument from the partial/with that wraps the PostProcess call.
- If you need late CSS injection, use a non-deferred resource with appropriate fingerprinting instead of PostProcess.
Example fix
// before (inside deferred partial)
{{ partial "head.html" (dict "defer" true ...) }}
{{ resources.Get "app.css" | resources.PostProcess }}
// after (PostProcess moved to non-deferred template)
{{ partial "head.html" ... }}
{{ resources.Get "app.css" | resources.PostProcess }} Defensive patterns
Strategy: validation
Validate before calling
{{/* Move resources.PostProcess out of any partial invoked with defer=true */}} Prevention
- Never place resources.PostProcess inside a deferred partial or with/defer block.
- Audit partials for PostProcess before adding defer.
When it happens
Trigger: Placing {{ (resources.Get "x.css" | resources.PostProcess) }} inside a template invoked via a `defer` argument (e.g. a deferred partial or a with/defer block).
Common situations: Refactoring a CSS/JS pipeline into a deferred partial for performance; using PostProcess in a header partial that is itself deferred; theme updates that introduced defer on partials that contain PostProcess.
Related errors
- failed to process shortcode
- must not provide more arguments than Resource and hash…
- must provide a Resource object
- must provide an URL and optionally an options map
- must provide one or more Resource objects to concat
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/0213c2e43ce1b9b3.
Report an issue: GitHub.
Appendix: source
Thrown at tpl/tplimpl/templatetransform.go:453
return
}
idArg = cmd.Args[0]
if !c.isWithDefer(idArg) {
return
}
deferArg := cmd.Args[1]
cmd.Args = []parse.Node{idArg}
l := doDefer.CopyList()
n := l.Nodes[0].(*parse.ActionNode)
inner := withNode.List.CopyList()
s := inner.String()
if strings.Contains(s, "resources.PostProcess") {
c.err = errors.New("resources.PostProcess cannot be used in a deferred template")
return
}
innerHash := hashing.XxHashFromStringHexEncoded(s)
deferredID := tpl.HugoDeferredTemplatePrefix + innerHash
c.deferNodes[deferredID] = inner
withNode.List = l
n.Pipe.Cmds[0].Args[1].(*parse.PipeNode).Cmds[0].Args[0].(*parse.StringNode).Text = deferredID
n.Pipe.Cmds[0].Args[2] = deferArg
}
func (c *templateTransformContext) applyTransformationsToNodes(nodes ...parse.Node) {
for _, node := range nodes {
c.applyTransformations(node)
}
}
View on GitHub (pinned to 52c9bd7908)