gohugoio/hugo · error

failed to compile whitelist pattern %q: %w

Error message

failed to compile whitelist pattern %q: %w

What it means

Returned by config/security.NewWhitelist when one of the configured security whitelist patterns fails regexp.Compile. Hugo's security policy (security.exec.allow, security.funcs.getenv, security.http.urls, etc.) is expressed as Go RE2 regular expressions, and any pattern (after stripping the '!' negation prefix) that is not valid RE2 aborts whitelist construction so the security policy is never partially applied.

Source

Thrown at config/security/whitelist.go:91

			acceptSome = true
			patternsStrings = append(patternsStrings, ps)
		}
	}

	if !acceptSome {
		return Whitelist{acceptNone: true}, nil
	}

	var allow, deny []*regexp.Regexp
	for _, p := range patternsStrings {
		raw := p
		negate := strings.HasPrefix(p, hglob.NegationPrefix)
		if negate {
			raw = p[len(hglob.NegationPrefix):]
		}
		re, err := regexp.Compile(raw)
		if err != nil {
			return Whitelist{}, fmt.Errorf("failed to compile whitelist pattern %q: %w", p, err)
		}
		if negate {
			deny = append(deny, re)
		} else {
			allow = append(allow, re)
		}
	}

	return Whitelist{allow: allow, deny: deny, patternsStrings: patternsStrings}, nil
}

// MustNewWhitelist creates a new Whitelist from zero or more patterns and panics on error.
func MustNewWhitelist(patterns ...string) Whitelist {
	w, err := NewWhitelist(patterns...)
	if err != nil {
		panic(err)
	}
	return w

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Fix the named pattern so it compiles as Go RE2 — test it with regexp.Compile or at regex101 (Golang flavor); RE2 has no lookarounds or backreferences.
  2. If you meant a glob like dart-sass*, write it as a regexp: '^dart-sass' or '^dart-sass.*$'.
  3. Keep the '!' only as a leading negation prefix; the rest of the string after '!' must itself be a valid regexp.
  4. Use the literal 'none' keyword if you want to deny everything instead of writing an empty/broken pattern.

Example fix

# before (hugo.toml)
[security.exec]
allow = ['^dart-sass(', 'pandoc(?=.exe)']
# after
[security.exec]
allow = ['^dart-sass', '^pandoc']
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate whitelist patterns before building config
for _, p := range patterns {
    if _, err := regexp.Compile(p); err != nil {
        return fmt.Errorf("invalid whitelist pattern %q: %w", p, err)
    }
}

Try / catch

cfg, err := security.NewWhitelist(patterns...)
if err != nil {
    // report the offending pattern verbatim to the user; do not fall back to allow-all
    return err
}

Prevention

When it happens

Trigger: Setting a value in the [security] section of hugo.toml (e.g. security.exec.allow = ['^dart-sass(']) that is not a valid Go regexp; unbalanced parens/brackets, invalid escapes like \d in single-quoted YAML contexts gone wrong, or RE2-unsupported syntax such as lookaheads (?=...) or backreferences \1. Also hits via HUGO_SECURITY_* environment overrides and via MustNewWhitelist in module code, which panics with this wrapped error.

Common situations: Developers paste shell glob patterns (dart-sass*) or PCRE with lookahead copied from other tools into security.exec.allow when whitelisting binaries like pandoc, asciidoctor or dart-sass-embedded; forgetting that Hugo expects anchored regexps, not globs; escaping errors introduced when editing TOML vs YAML config formats.

Related errors


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