{"id":"25b070309e42b5ec","repo":"gohugoio/hugo","slug":"expected-template-but-none-provided","errorCode":null,"errorMessage":"expected template, but none provided","messagePattern":"expected template, but none provided","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/tplimpl/templatetransform.go","lineNumber":77,"sourceCode":"\tlookupFn func(name string, in *TemplInfo) *TemplInfo,\n) *templateTransformContext {\n\treturn &templateTransformContext{\n\t\tt:                t,\n\t\tlookupFn:         lookupFn,\n\t\tstore:            store,\n\t\tvisited:          make(map[string]bool),\n\t\ttemplateNotFound: make(map[string]bool),\n\t\tdeferNodes:       make(map[string]*parse.ListNode),\n\t}\n}\n\nfunc applyTemplateTransformers(\n\tt *TemplInfo,\n\tstore *TemplateStore,\n\tlookupFn func(name string, in *TemplInfo) *TemplInfo,\n) (*templateTransformContext, error) {\n\tif t == nil {\n\t\treturn nil, errors.New(\"expected template, but none provided\")\n\t}\n\n\tc := newTemplateTransformContext(t, store, lookupFn)\n\tc.t.ParseInfo = defaultParseInfo\n\ttree := getParseTree(t.Template)\n\tif tree == nil {\n\t\tpanic(fmt.Errorf(\"template %s not parsed\", t))\n\t}\n\n\tif err := c.applyTransformationsAndSetReturnWrapper(tree); err != nil {\n\t\treturn c, fmt.Errorf(\"failed to transform template %q: %w\", t.Name(), err)\n\t}\n\n\treturn c, c.err\n}\n\nfunc getParseTree(templ tpl.Template) *parse.Tree {\n\tif text, ok := templ.(*texttemplate.Template); ok {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/tplimpl/templatetransform.go#L59-L95","documentation":"`applyTemplateTransformers` (tpl/tplimpl/templatetransform.go:77) is the internal pass that rewrites a parsed Hugo template (partial return handling, defer nodes, lookups). It guards against being handed a nil `*TemplInfo`; a nil here means an upstream lookup or parse produced no template. This is an internal invariant error, not a user-facing template syntax error.","triggerScenarios":"Hugo's template store invoking the transformer chain with a nil TemplInfo — e.g. a template that failed to parse or a lookup path that returned nil being passed into the transform stage. End users cannot trigger it directly through template functions.","commonSituations":"Almost always indicates a Hugo bug or a broken template store state — e.g. after a regression in the 0.146+ template store rewrite, an unusual layouts arrangement exposing an unhandled lookup path, or a custom fork/embedding of hugolib passing nil templates. Rarely seen in normal site builds.","solutions":["Upgrade to the latest Hugo release; if it persists, this is likely an internal bug.","Run `hugo --logLevel debug` to identify which template/layout triggers the transform and try removing or simplifying it to isolate the trigger.","Report the issue to gohugo.io/GitHub with the minimal reproducing layouts, since this error signals an internal invariant violation.","If embedding hugolib programmatically, ensure you never pass a nil template into the template store APIs."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"{{/* never call template/partial helpers with an empty name */}}\n{{ $name := .Params.layoutPartial }}\n{{ if and $name (templates.Exists (printf \"partials/%s\" $name)) }}\n  {{ partial $name . }}\n{{ end }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure every layout/partial file you reference actually contains template content, not an empty file","Guard dynamically computed template names against empty strings before invoking them","After upgrading Hugo, run a full build — empty or stub templates that previously passed may now be rejected","Delete placeholder zero-byte template files from layouts/ instead of leaving them to be parsed"],"tags":["hugo","internal","templates","nil-check"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}