gohugoio/hugo · error

%s: shortcode %q does not evaluate .Inner or .InnerDeindent,

Error message

%s: shortcode %q does not evaluate .Inner or .InnerDeindent, yet a closing tag was provided

What it means

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.

Source

Thrown at hugolib/shortcode.go:650

				if !sc.templ.ParseInfo.IsInner {
					return sc, nil
				}
			}

		case currItem.IsShortcodeClose():
			closed = true
			next := pt.Peek()
			if !sc.isInline {
				if !sc.needsInner() {
					if next.IsError() {
						// return that error, more specific
						continue
					}
					name := sc.name
					if name == "" {
						name = next.ValStr(source)
					}
					return nil, fmt.Errorf("%s: shortcode %q does not evaluate .Inner or .InnerDeindent, yet a closing tag was provided", errorPrefix, name)
				}
			}
			if next.IsRightShortcodeDelim() {
				// self-closing
				pt.Consume(1)
			} else {
				sc.isClosing = true
				pt.Consume(2)
			}
			return sc, nil
		case currItem.IsText():
			sc.inner = append(sc.inner, currItem.ValStr(source))
		case currItem.IsShortcodeName():

			sc.name = currItem.ValStr(source)

			// Used to check if the template expects inner content,
			// so just pick one arbitrarily with the same name.

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Change the content to the self-closed/standalone form: {{< name >}} or {{< name />}} with no closing tag.
  2. If the shortcode should wrap content, add a use of .Inner (or .InnerDeindent) to layouts/_shortcodes/name.html.
  3. 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.

Example fix

{{/* before: layouts/_shortcodes/note.html */}}
<div class="note">Note</div>

{{/* after */}}
<div class="note">{{ .Inner | markdownify }}</div>
Defensive patterns

Strategy: validation

Validate before calling

// Check the template uses .Inner before using paired syntax
// grep -l '\.Inner' layouts/_shortcodes/<name>.html || echo 'use self-closing {{< name />}}'

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/cd8d67770a5be1d9.json. Report an issue: GitHub ↗.