gohugoio/hugo · critical

unknown shortcode token %q (number of tokens: %d)

Error message

unknown shortcode token %q (number of tokens: %d)

What it means

A panic raised by the token handler in page__content.go's content-rendering path when, after markdown processing, Hugo finds a HUGOSHORTCODE-style placeholder token in the output that has no matching entry in ct.contentPlaceholders. The code comments this as "should never happen" — it indicates internal state corruption: a placeholder survived into rendered content without a registered renderer.

Source

Thrown at hugolib/page__content.go:562

			}

			// There are one or more replacement tokens to be replaced.
			var hasShortcodeVariants bool
			tokenHandler := func(ctx context.Context, token string) ([]byte, error) {
				if token == tocShortcodePlaceholder {
					return []byte(ct.tableOfContentsHTML), nil
				}
				renderer, found := ct.contentPlaceholders[token]
				if found {
					repl, more, err := renderer.renderShortcode(ctx)
					if err != nil {
						return nil, err
					}
					hasShortcodeVariants = hasShortcodeVariants || more
					return repl, nil
				}
				// This should never happen.
				panic(fmt.Errorf("unknown shortcode token %q (number of tokens: %d)", token, len(ct.contentPlaceholders)))
			}

			b, err = expandShortcodeTokens(ctx, b, tokenHandler)
			if err != nil {
				return nil, err
			}
			if hasShortcodeVariants {
				cp.po.p.incrPageOutputTemplateVariation()
			}

			var result contentSummary
			if c.pi.hasSummaryDivider {
				s := string(b)
				summarized := page.ExtractSummaryFromHTMLWithDivider(cp.po.p.m.pageConfigSource.ContentMediaType, s, internalSummaryDividerBase)
				result.summary = page.Summary{
					Text:      template.HTML(summarized.Summary()),
					Type:      page.SummaryTypeManual,
					Truncated: summarized.Truncated(),

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Restart `hugo server` (or run `hugo --gc` and clear resources/_gen and the cacheDir) to rule out stale cached content state.
  2. Search content and layouts for anything emitting the literal internal placeholder pattern (e.g. `grep -r HAHAHUGOSHORTCODE content layouts`) and remove it.
  3. Check whether a render hook or shortcode copies raw page source (.RawContent) into output — that duplicates placeholders; use .Content or rework the hook.
  4. If reproducible on a clean build, minimize the site and report it as a bug at github.com/gohugoio/hugo — this path is an internal invariant violation (it panics).
Defensive patterns

Strategy: validation

Validate before calling

// don't manipulate rendered content in ways that split/drop shortcode placeholder tokens
// e.g. avoid truncating .Content or regex-replacing over raw placeholder markers before rendering completes

Try / catch

if _, err := p.Content(ctx); err != nil && strings.Contains(err.Error(), "unknown shortcode token") {
    // internal token mismatch — usually a content-mangling markup hook or truncation
    return err
}

Prevention

When it happens

Trigger: expandShortcodeTokens encounters a placeholder string in Goldmark output that isn't in the placeholder map. In practice: content or a markdown render hook that synthesizes/duplicates text containing a raw `HAHAHUGOSHORTCODE` placeholder, or a Hugo bug where placeholder bookkeeping diverges between parse and render (e.g. cached content reused across edits in `hugo server`).

Common situations: Render hooks or shortcodes that echo page content verbatim (duplicating placeholder tokens); pathological content literally containing the internal placeholder marker; stale-cache states in long-running `hugo server` sessions after rapid edits; rarely, genuine regressions in a new Hugo release.

Related errors


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