gohugoio/hugo · error

no earlier definition of shortcode %q found

Error message

no earlier definition of shortcode %q found

What it means

Inline shortcodes ({{< name.inline >}}...{{< /name.inline >}}) define their template body in the content file on first use; subsequent uses of {{< name.inline />}} without a body reuse that earlier definition, looked up under a per-page template path. If Hugo can't find a previously parsed definition with that name on the same page, it fails with this error, because there is no template body to execute.

Source

Thrown at hugolib/shortcode.go:399

			var err error
			tmpl, err = ts.TextParse(templatePath, templStr)
			if err != nil {
				if isRenderString {
					return zeroShortcode, p.wrapError(err)
				}
				fe := herrors.NewFileErrorFromName(err, p.File().Filename())
				pos := fe.Position()
				pos.LineNumber += p.posOffset(sc.pos).LineNumber
				fe = fe.UpdatePosition(pos)
				return zeroShortcode, p.wrapError(fe)
			}

		} else {
			// Re-use of shortcode defined earlier in the same page.
			tmpl = ts.TextLookup(templatePath)
			if tmpl == nil {
				return zeroShortcode, fmt.Errorf("no earlier definition of shortcode %q found", sc.name)
			}
		}
	} else {
		ofCount := map[string]int{}
		include := func(match *tplimpl.TemplInfo) bool {
			ofCount[match.D.OutputFormat]++
			return true
		}
		base, layoutDescriptor := po.GetInternalTemplateBasePathAndDescriptor()

		// With shortcodes/mymarkdown.md (only), this allows {{% mymarkdown %}} when rendering HTML,
		// but will not resolve any template when doing {{< mymarkdown >}}.
		layoutDescriptor.AlwaysAllowPlainText = sc.doMarkup
		q := tplimpl.TemplateQuery{
			Path:     base,
			Name:     sc.name,
			Category: tplimpl.CategoryShortcode,
			Desc:     layoutDescriptor,

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Add or move the full defining occurrence ({{< name.inline >}}...{{< /name.inline >}}) before any self-closed reuse on the same page.
  2. If the logic is shared across pages, convert it to a regular shortcode file under layouts/_shortcodes/ instead of an inline shortcode.
  3. Confirm 'security.enableInlineShortcodes = true' is set — with it off inline shortcodes render empty, but naming/order errors like this still indicate the definition is missing.

Example fix

<!-- before (content/post.md) -->
{{< greet.inline />}}
{{< greet.inline >}}Hello {{ .Get 0 }}{{< /greet.inline >}}

<!-- after -->
{{< greet.inline >}}Hello {{ .Get 0 }}{{< /greet.inline >}}
{{< greet.inline />}}
Defensive patterns

Strategy: validation

Validate before calling

// Before overriding, confirm the shortcode exists upstream
// e.g. check themes/<theme>/layouts/_shortcodes/<name>.html exists
if _, err := os.Stat(filepath.Join(themeDir, "layouts/_shortcodes", name+".html")); err != nil {
    return fmt.Errorf("no base shortcode %q to inherit from", name)
}

Prevention

When it happens

Trigger: Using a self-closed inline shortcode ({{< foo.inline />}}) before — or without — a closed defining occurrence ({{< foo.inline >}}body{{< /foo.inline >}}) earlier in the same page. Inline shortcode definitions are scoped per page (templatePath includes p.Path()), so a definition on another page does not count.

Common situations: Reordering content so the self-closed reuse appears above the definition; expecting inline shortcode definitions to be shared across pages or from an archetype; copy-pasting only the reuse call; using them in .RenderString contexts without the definition.

Related errors


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