{"record":{"id":"e5aaf6d571188963","repo":"gohugoio/hugo","slug":"templates-defer-cannot-be-used-inside-a-partialcac","errorCode":null,"errorMessage":"templates.Defer cannot be used inside a partialCached partial; use partial instead, or move templates.Defer to the calling template","messagePattern":"templates\\.Defer cannot be used inside a partialCached partial; use partial instead, or move templates\\.Defer to the calling template","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/templates/templates.go","lineNumber":65,"sourceCode":"\n// Exists returns whether the template with the given name exists.\n// Note that this is the Unix-styled relative path including filename suffix,\n// e.g. partials/header.html\nfunc (ns *Namespace) Exists(name string) bool {\n\treturn ns.deps.GetTemplateStore().HasTemplate(name)\n}\n\n// Defer defers the execution of a template block.\nfunc (ns *Namespace) Defer(ctx context.Context, args ...any) (bool, error) {\n\t// Prevent defer from being used in content adapters,\n\t// that just doesn't work.\n\tns.deps.Site.CheckReady()\n\n\t// Reject use inside a partialCached body: the cached output retains the\n\t// deferred placeholder across rebuilds while the executions map is reset,\n\t// which used to cause a panic in executeDeferredTemplates. See issue #13492.\n\tif tpl.Context.IsInPartialCached.Get(ctx) {\n\t\treturn false, fmt.Errorf(\"templates.Defer cannot be used inside a partialCached partial; use partial instead, or move templates.Defer to the calling template\")\n\t}\n\n\tif len(args) != 0 {\n\t\treturn false, fmt.Errorf(\"Defer does not take any arguments\")\n\t}\n\treturn true, nil\n}\n\nvar defferedIDCounter atomic.Uint64\n\ntype DeferOpts struct {\n\t// Optional cache key. If set, the deferred block will be executed\n\t// once per unique key.\n\tKey string\n\n\t// Optional data context to use when executing the deferred block.\n\tData any\n}","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/templates/templates.go#L47-L83","documentation":"Thrown by templates.Defer when tpl.Context.IsInPartialCached is set on the context, i.e. the Defer block lives inside a partialCached body. The cached output retains the deferred placeholder across rebuilds while the executions map resets, which previously caused a panic in executeDeferredTemplates (issue #13492).","triggerScenarios":"Using {{ templates.Defer (…) }} …{{ end }} inside a partial that is invoked via partialCached. The guard fires at the start of Defer regardless of arguments.","commonSituations":"Migrating from resources.PostProcess to templates.Defer inside a cached partial, or wrapping a deferred heavy block in partialCached for performance. The fix is structural: the deferred block must not be cached.","solutions":["Switch the calling partial from partialCached to plain partial.","Move the templates.Defer block up to the page/layout template that calls the partial.","Split the partial so the deferred portion lives outside the cached boundary.","Re-evaluate whether caching is needed if the content depends on deferred data."],"exampleFix":"// before (Defer inside partialCached body):\n{{ partialCached \"widget.html\" . }}  // widget.html contains templates.Defer\n// after (call without caching):\n{{ partial \"widget.html\" . }}","handlingStrategy":"validation","validationCode":"{{ if not $.InPartialCached }}{{ templates.Defer }}…{{ end }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never place templates.Defer inside a partialCached body.","Use plain partial for any partial containing a Defer block.","Move deferred blocks to the calling layout/page template."],"tags":["templates","defer","partialcached","regression-guard"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}