{"id":"ea015ca32d30f80a","repo":"gohugoio/hugo","slug":"unrecognized-render-hook-template","errorCode":null,"errorMessage":"unrecognized render hook template","messagePattern":"unrecognized render hook template","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/tplimpl/templatestore.go","lineNumber":1900,"sourceCode":"\t\t}\n\t\td.LayoutFromTemplate = \"\"\n\t}\n\n\tif d.LayoutFromTemplate == d.Kind {\n\t\td.LayoutFromTemplate = \"\"\n\t}\n\n\tk1 = strings.TrimPrefix(k1, \"/_default\")\n\tif k1 == \"/\" {\n\t\tk1 = \"\"\n\t}\n\n\tif category == CategoryMarkup {\n\t\t// We store all template nodes for a given directory on the same level.\n\t\tk1 = strings.TrimSuffix(k1, \"/_markup\")\n\t\tv, found := strings.CutPrefix(d.LayoutFromTemplate, \"render-\")\n\t\tif !found {\n\t\t\treturn \"\", \"\", 0, TemplateDescriptor{}, nil, fmt.Errorf(\"unrecognized render hook template\")\n\t\t}\n\t\thyphenIdx := strings.Index(v, \"-\")\n\n\t\td.Variant1 = v\n\t\tif hyphenIdx > 0 {\n\t\t\td.Variant1 = v[:hyphenIdx]\n\t\t\td.Variant2 = v[hyphenIdx+1:]\n\t\t}\n\n\t\td.LayoutFromTemplate = \"\" // This allows using page layout as part of the key for lookups.\n\t}\n\n\treturn k1, k2, category, d, vactorStore, nil\n}\n\nfunc (s *TemplateStore) transformTemplates() error {\n\tlookup := func(name string, in *TemplInfo) *TemplInfo {\n\t\tif in.D.IsPlainText {","sourceCodeStart":1882,"sourceCodeEnd":1918,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/tplimpl/templatestore.go#L1882-L1918","documentation":"Templates under a `_markup` directory are render hooks, and Hugo requires their filenames to start with the `render-` prefix (e.g. render-link.html, render-image.html) so it can derive the hook kind (Variant1/Variant2) from the name. A file in _markup whose name lacks that prefix cannot be classified, and template-store insertion fails with this error.","triggerScenarios":"Placing any template in layouts/_markup/ (or layouts/**/_markup/) whose base name does not begin with `render-`, e.g. layouts/_markup/link.html or layouts/_markup/render_link.html (underscore instead of hyphen).","commonSituations":"Misremembering the naming convention (link.html instead of render-link.html); using an underscore (render_codeblock.html); stray helper partials or backup files (render-link.html.bak, foo.html) saved inside _markup; migrating from older layouts where hooks lived elsewhere.","solutions":["Rename the file to the render-<kind>[-<variant>] convention, e.g. layouts/_markup/render-link.html or render-codeblock-mermaid.html.","Move non-hook helper templates out of the _markup directory (put partials under layouts/_partials/).","Delete editor backup/temp files accidentally left inside _markup."],"exampleFix":"# before\nlayouts/_markup/link.html\n# after\nlayouts/_markup/render-link.html","handlingStrategy":"validation","validationCode":"# render hooks must live under a recognized path/name\nls layouts/_markup/  # e.g. render-link.html, render-image.html, render-heading.html, render-codeblock-<lang>.html","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Name render hooks exactly render-link, render-image, render-heading, render-blockquote, render-passthrough, render-table, or render-codeblock[-lang]","Place them under layouts/_markup/ (current spec), not arbitrary directories","Don't invent custom render-* names — only the documented hook kinds are recognized","After upgrading Hugo, re-check hook naming against the current docs since recognized names evolve"],"tags":["hugo","render-hooks","templates","markdown"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}