{"id":"4fa2dcbd99298cc4","repo":"gohugoio/hugo","slug":"defer-does-not-take-any-arguments","errorCode":null,"errorMessage":"Defer does not take any arguments","messagePattern":"Defer does not take any arguments","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/templates/templates.go","lineNumber":69,"sourceCode":"func (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}\n\n// Inner executes the inner content of a partial decorator.\n// Note that there is only one inner block per partial decorator, but inner may be called multiple times with, typically, different data.\nfunc (ns *Namespace) Inner(ctx context.Context, data any) (any, error) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/templates/templates.go#L51-L87","documentation":"`templates.Defer` must be invoked with no positional arguments; it is designed to be used as `{{ with (templates.Defer) }}` or with options attached via a dict in the documented `(templates.Defer (dict ...))` form handled elsewhere — the validated call path here rejects any leftover args (tpl/templates/templates.go:68-70). The check exists because arguments passed positionally would be silently ignored, so Hugo fails fast instead.","triggerScenarios":"Calling `{{ with (templates.Defer .) }}` or `{{ templates.Defer \"key\" }}` — passing the page context, a string key, or any other positional value where the function expects none.","commonSituations":"Assuming Defer takes a data context like `partial` does; trying to pass a cache key directly instead of via the options dict form shown in the docs; copy-paste from an incorrect snippet.","solutions":["Remove the arguments: use `{{ with (templates.Defer) }}...{{ end }}`.","To pass a key or data, use the documented options form: `{{ with (templates.Defer (dict \"key\" \"global\" \"data\" .)) }}` — inside the block, the data is available as the context.","Consult the templates.Defer docs for the exact supported options (key, data)."],"exampleFix":"<!-- before -->\n{{ with (templates.Defer .) }}...{{ end }}\n<!-- after -->\n{{ with (templates.Defer (dict \"data\" .)) }}...{{ end }}","handlingStrategy":"validation","validationCode":"{{/* correct usage — no arguments, options via with-block context: */}}\n{{ with (templates.Defer (dict \"key\" \"global\")) }}...{{ end }}\n{{/* wrong: {{ templates.Defer . }} */}}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call templates.Defer with zero positional arguments; pass options as a dict inside `with (templates.Defer (dict ...))`","Don't pipe the page context into Defer — capture what you need in the dict's \"data\" key instead"],"tags":["hugo","templates","defer","template-functions"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}