{"id":"cd8d67770a5be1d9","repo":"gohugoio/hugo","slug":"s-shortcode-q-does-not-evaluate-inner-or-inne","errorCode":null,"errorMessage":"%s: shortcode %q does not evaluate .Inner or .InnerDeindent, yet a closing tag was provided","messagePattern":"(.+?): shortcode %q does not evaluate \\.Inner or \\.InnerDeindent, yet a closing tag was provided","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hugolib/shortcode.go","lineNumber":650,"sourceCode":"\t\t\t\tif !sc.templ.ParseInfo.IsInner {\n\t\t\t\t\treturn sc, nil\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase currItem.IsShortcodeClose():\n\t\t\tclosed = true\n\t\t\tnext := pt.Peek()\n\t\t\tif !sc.isInline {\n\t\t\t\tif !sc.needsInner() {\n\t\t\t\t\tif next.IsError() {\n\t\t\t\t\t\t// return that error, more specific\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tname := sc.name\n\t\t\t\t\tif name == \"\" {\n\t\t\t\t\t\tname = next.ValStr(source)\n\t\t\t\t\t}\n\t\t\t\t\treturn nil, fmt.Errorf(\"%s: shortcode %q does not evaluate .Inner or .InnerDeindent, yet a closing tag was provided\", errorPrefix, name)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif next.IsRightShortcodeDelim() {\n\t\t\t\t// self-closing\n\t\t\t\tpt.Consume(1)\n\t\t\t} else {\n\t\t\t\tsc.isClosing = true\n\t\t\t\tpt.Consume(2)\n\t\t\t}\n\t\t\treturn sc, nil\n\t\tcase currItem.IsText():\n\t\t\tsc.inner = append(sc.inner, currItem.ValStr(source))\n\t\tcase currItem.IsShortcodeName():\n\n\t\t\tsc.name = currItem.ValStr(source)\n\n\t\t\t// Used to check if the template expects inner content,\n\t\t\t// so just pick one arbitrarily with the same name.","sourceCodeStart":632,"sourceCodeEnd":668,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/hugolib/shortcode.go#L632-L668","documentation":"Hugo inspects each shortcode template at parse time to see whether it references .Inner or .InnerDeindent. If the template does not, the shortcode is treated as standalone, and encountering a closing tag ({{< /name >}}) for it in content is an error: the parser would otherwise swallow the enclosed content and silently drop it. This check makes the content/template mismatch explicit.","triggerScenarios":"Content uses the paired form {{< name >}}...{{< /name >}} but layouts/_shortcodes/name.html never accesses .Inner or .InnerDeindent (needsInner() is false during extractShortcode). Only applies to non-inline shortcodes; inline shortcodes are exempt from the check.","commonSituations":"Refactoring a shortcode template and removing its .Inner usage while content still uses closing tags; using a theme's shortcode with the wrong calling convention; .Inner referenced only behind a construct the parser can't detect, or accessed via a partial rather than directly in the shortcode template.","solutions":["Change the content to the self-closed/standalone form: {{< name >}} or {{< name />}} with no closing tag.","If the shortcode should wrap content, add a use of .Inner (or .InnerDeindent) to layouts/_shortcodes/name.html.","If .Inner is consumed indirectly (e.g. passed to a partial), reference it directly in the shortcode template so Hugo's parse-info detection sees it."],"exampleFix":"{{/* before: layouts/_shortcodes/note.html */}}\n<div class=\"note\">Note</div>\n\n{{/* after */}}\n<div class=\"note\">{{ .Inner | markdownify }}</div>","handlingStrategy":"validation","validationCode":"// Check the template uses .Inner before using paired syntax\n// grep -l '\\.Inner' layouts/_shortcodes/<name>.html || echo 'use self-closing {{< name />}}'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use paired {{< name >}}...{{< /name >}} only when the template evaluates .Inner or .InnerDeindent","Switch to self-closing {{< name />}} for shortcodes that take no body","When authoring a shortcode meant to wrap content, reference .Inner even if only to discard it deliberately"],"tags":["hugo","shortcode","template","inner","content"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}