crowdsecurity/crowdsec · error

baked-in initial_bundle.js.gz is empty (was `go generate` ru

Error message

baked-in initial_bundle.js.gz is empty (was `go generate` run?)

What it means

ChallengeRuntime.seedCacheFromInitialBundle decompresses the baked-in initial_bundle.js.gz (embedded via go:embed from `go generate`) to seed the challenge code cache. If the embedded byte slice is empty, the build artifact was never generated, so it fails with this self-diagnosing error pointing at `go generate`.

Source

Thrown at pkg/appsec/challenge/static_bundle.go:52

	initialBundleOnce sync.Once
	initialBundleErr  error
)

// FPScannerJS is the public, unobfuscated fpscanner bundle served at
// ChallengeFPScannerPath. Re-exported so the dispatcher can serve it via the
// challenge package alongside PowWorkerJS.
var FPScannerJS = challengejs.FPScannerJS

// seedCacheFromInitialBundle decompresses the build-time obfuscated challenge
// code (initial_bundle.js.gz) and stores it as the static code served on every
// challenge page. Cheap (~ms) — eliminates the obfuscation that startup would
// otherwise pay.
func (c *ChallengeRuntime) seedCacheFromInitialBundle() error {
	initialBundleOnce.Do(func() {
		decompressStart := time.Now()

		if len(initialBundleGz) == 0 {
			initialBundleErr = errors.New("baked-in initial_bundle.js.gz is empty (was `go generate` run?)")
			return
		}

		gz, err := gzip.NewReader(bytes.NewReader(initialBundleGz))
		if err != nil {
			initialBundleErr = fmt.Errorf("gzip reader for initial bundle: %w", err)
			return
		}
		defer gz.Close()

		decoded, err := io.ReadAll(gz)
		if err != nil {
			initialBundleErr = fmt.Errorf("decompress initial bundle: %w", err)
			return
		}
		initialBundle = string(decoded)

		c.log().WithFields(log.Fields{

View on GitHub (pinned to 909b515798)

Solutions

  1. Run `go generate ./pkg/appsec/challenge/...` (which executes the js/cmd/bundle and initialbundle generators) and rebuild.
  2. Verify the generated initial_bundle.js.gz exists and is non-empty in the package directory before building.
  3. Check CI/build scripts include the generate step prior to `go build`.
  4. Ensure the file isn't excluded by .gitignore/clean rules in your checkout.

Example fix

# before: building without codegen
go build ./...
# after
go generate ./pkg/appsec/challenge/...
go build ./...
Defensive patterns

Strategy: validation

Validate before calling

// build-time check the embedded artifact is non-empty
//go:embed initial_bundle.js.gz
var initialBundleGz []byte

func init() {
    if len(initialBundleGz) == 0 {
        panic("initial_bundle.js.gz is empty: run `go generate` before building")
    }
}

Try / catch

if err := rt.seedCacheFromInitialBundle(); err != nil {
    // error already names the fix; surface it at startup, not per-request
    return nil, fmt.Errorf("challenge runtime init: %w", err)
}

Prevention

When it happens

Trigger: NewChallengeRuntime calls seedCacheFromInitialBundle; on first use initialBundleOnce finds len(initialBundleGz) == 0 (static_bundle.go:52).

Common situations: Building from a source checkout without running `go generate` first; a build pipeline that skips codegen; the generated file was deleted or gitignored and never regenerated; embed directive pointing at an empty file.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/b377a5a1cacf6093. Report an issue: GitHub.