gohugoio/hugo · error

failed to compile cache buster source %q: %w

Error message

failed to compile cache buster source %q: %w

What it means

Raised by CacheBuster.CompileConfig when the `source` field of a `build.cachebusters` entry is not a valid Go RE2 regexp. The source pattern decides which changed file triggers cache busting, and its capture groups feed `$1`-style substitutions in the target pattern; compilation happens eagerly at config load, so a bad pattern stops the build. Error 40 is the outer wrapper of this same failure.

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 8a468df065)

Solutions

  1. Fix the `source` regexp quoted in the error to valid RE2 syntax; close all groups and character classes.
  2. Escape literal metacharacters, e.g. `hugo_stats\\.json` in TOML basic strings or use literal strings: `source = 'assets/.*\.(js|css)$'`.
  3. Avoid lookarounds/backreferences; restructure the pattern with alternation and anchors instead.

Example fix

# before (hugo.toml)
[[build.cachebusters]]
source = "assets/.*\\.(js|css"
target = "(js|css)"

# after
[[build.cachebusters]]
source = 'assets/.*\.(js|css)$'
target = '(js|css)'
Defensive patterns

Strategy: validation

Validate before calling

for _, cb := range cfg.Build.CacheBusters {
    if _, err := regexp.Compile(cb.Source); err != nil {
        return fmt.Errorf("build.cachebusters source %q: %w", cb.Source, err)
    }
}

Try / catch

if err := buildCfg.CompileConfig(logger); err != nil {
    // names the bad [build.cachebusters].source pattern — it must be a valid RE2 regexp
    return err
}

Prevention

When it happens

Trigger: `hugo` or `hugo server` startup with `[[build.cachebusters]]` whose `source` fails regexp.Compile — unclosed groups/classes like `source = "assets/watching/hugo_stats\\.json("`, PCRE-only lookarounds, or invalid escapes.

Common situations: Treating `source` as a glob (`**` patterns); customizing the default cachebusters (hugo_stats.json / postcss / tailwind setups) and breaking the regexp; unescaped dots or parens in file paths; TOML backslash-escaping mistakes.

Related errors


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