gohugoio/hugo · error

failed to compile cache buster source

Error message

failed to compile cache buster source %q: %w

What it means

The inner error of CacheBuster.CompileConfig: it compiles the `source` field as a Go regexp (regexp.Compile). If source is empty, regexp.Compile succeeds with a match-all-empty; failure means genuinely malformed regexp syntax. This is the leaf cause wrapped by error 273 when called from BuildConfig.CompileConfig's loop.

Solutions

  1. Validate `source` with Go regexp (RE2) semantics.
  2. Ensure any `(` has a matching `)`; escape literal metacharacters.
  3. Remember `target` can reference `$1`, `$2`... from source groups.

Example fix

# before
[[build.cacheBusters]]
source = ".git/.*"
target = "\.git\\."

# after
[[build.cacheBusters]]
source = "\.git/.*"
target = "\.git\\."
Defensive patterns

Strategy: validation

Validate before calling

python3 - <<'PY'
import tomllib,re
cfg=tomllib.loads(open('hugo.toml').read())
for cb in cfg.get('build',{}).get('cacheBusters',[]):
    try: re.compile(cb['source'])
    except re.error as e: print(f"bad cacheBuster source {cb['source']!r}: {e}")
print("cacheBuster source ok")
PY

Prevention

When it happens

Trigger: A `[[build.cacheBusters]]` `source` with invalid Go regexp syntax (unbalanced paren, bad escape). Because the source regexp also drives capture groups substituted into `target`, malformed groups break target compilation too.

Common situations: Writing cache busters for asset fingerprinting/dev-server and using glob/PCRE syntax instead of RE2; unbalanced capture group.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/0cdfc64c5ecf314b. Report an issue: GitHub.

Appendix: source

Thrown at config/commonConfig.go:411

	// Trigger for files matching this regexp.
	Source string

	// Cache bust targets matching this regexp.
	// This regexp can contain group matches (e.g. $1) from the source regexp.
	Target string

	compiledSource func(string) func(string) bool
}

func (c *CacheBuster) CompileConfig(logger loggers.Logger) error {
	if c.compiledSource != nil {
		return nil
	}

	source := c.Source
	sourceRe, err := regexp.Compile(source)
	if err != nil {
		return fmt.Errorf("failed to compile cache buster source %q: %w", c.Source, err)
	}
	target := c.Target
	var compileErr error
	debugl := logger.Logger().WithLevel(logg.LevelDebug).WithField(loggers.FieldNameCmd, "cachebuster")

	c.compiledSource = func(s string) func(string) bool {
		m := sourceRe.FindStringSubmatch(s)
		matchString := "no match"
		match := m != nil
		if match {
			matchString = "match!"
		}
		debugl.Logf("Matching %q with source %q: %s", s, source, matchString)
		if !match {
			return nil
		}
		groups := m[1:]
		currentTarget := target

View on GitHub (pinned to 52c9bd7908)