gohugoio/hugo · critical
illegal state in content; shortcode token missing end delim
Error message
illegal state in content; shortcode token missing end delim
What it means
After markdown rendering, Hugo replaces placeholder tokens (prefix ... 'HBHB' end marker) in the rendered output with the actual shortcode results. This error means a token's start prefix was found but its 'HBHB' end delimiter was not — the placeholder was corrupted between insertion and expansion. It is an internal invariant violation ('should never happen'), not a user syntax error per se.
Source
Thrown at hugolib/shortcode.go:744
ctx context.Context,
source []byte,
tokenHandler func(ctx context.Context, token string) ([]byte, error),
) ([]byte, error) {
start := 0
pre := []byte(shortcodePlaceholderPrefix)
post := []byte("HBHB")
pStart := []byte("<p>")
pEnd := []byte("</p>")
k := bytes.Index(source[start:], pre)
for k != -1 {
j := start + k
postIdx := bytes.Index(source[j:], post)
if postIdx < 0 {
// this should never happen, but let the caller decide to panic or not
return nil, errors.New("illegal state in content; shortcode token missing end delim")
}
end := j + postIdx + 4
key := string(source[j:end])
newVal, err := tokenHandler(ctx, key)
if err != nil {
return nil, err
}
// Issue #1148: Check for wrapping p-tags <p>
if j >= 3 && bytes.Equal(source[j-3:j], pStart) {
if (k+4) < len(source) && bytes.Equal(source[end:end+4], pEnd) {
j -= 3
end += 4
}
}
// This and other cool slice tricks: https://github.com/golang/go/wiki/SliceTricksView on GitHub ↗ (pinned to 8a468df065)
Solutions
- Identify which page fails and simplify: temporarily remove shortcodes one at a time to find the placement (e.g. inside a code block, link title, or attribute) whose rendering mangles the token.
- Check custom render hooks/markup filters that rewrite rendered text and exclude Hugo's shortcode placeholder tokens from transformation.
- Update Hugo to the latest release, and if it still reproduces with a minimal case, report it as a bug — this state indicates an internal invariant break.
Defensive patterns
Strategy: validation
Validate before calling
// Detect unterminated shortcode delimiters in content
// grep -nE '\{\{[<%]([^}]|\}[^}])*$' content/**/*.md Try / catch
if err := h.Build(cfg); err != nil {
// 'missing end delim' means a {{< or {{% was never closed with >}} / %}}
// find the last shortcode open in the named file
return err
} Prevention
- Every {{< must be terminated with >}} and every {{% with %}} on the same logical token
- Watch for truncated files from bad merges or generators cutting content mid-shortcode
- Don't mix delimiter styles in one call ({{< ... %}} is malformed)
- Add an editor snippet that inserts both delimiters at once so they can't be left unbalanced
When it happens
Trigger: expandShortcodeTokens finding the shortcode placeholder prefix in rendered content without a following 'HBHB' marker. This occurs when the markdown renderer or a filter mutates, splits, or truncates the placeholder string — e.g. a render hook, custom Goldmark extension, or a template transformation altering the token text.
Common situations: Custom markdown render hooks or output filters that transform text containing the placeholder; shortcodes placed in contexts where the renderer escapes or breaks the token (e.g. inside code processing or transformed attributes); very rarely a Hugo bug after version upgrades — historically reported around unusual shortcode placement.
Related errors
- failed to render shortcode %q: %w
- failed to render shortcode: %w
- unknown shortcode token %q (number of tokens: %d)
- conf must be set
- npm pack: failed to marshal package.json with updated worksp
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/658acd794984031f.json.
Report an issue: GitHub ↗.