crowdsecurity/crowdsec · error

decompress initial bundle: %w

Error message

decompress initial bundle: %w

What it means

After opening the embedded initial_bundle.js.gz, the runtime reads the decompressed content with io.ReadAll; a failure here means the gzip stream is truncated or corrupted mid-decompression. The error is stored in initialBundleErr and returned for every request to the bundle endpoint. It signals a broken embedded asset in the binary.

Source

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

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{
			"compressed_bytes":   len(initialBundleGz),
			"decompressed_bytes": len(initialBundle),
			"duration_ms":        time.Since(decompressStart).Milliseconds(),
		}).Debug("decompressed baked-in obfuscated challenge code")
	})

	if initialBundleErr != nil {
		return initialBundleErr
	}
	if initialBundle == "" {
		return errors.New("initial bundle is empty after decompression")
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Regenerate the asset: delete initial_bundle.js.gz, re-run `go generate`, and rebuild
  2. Validate the asset: `gzip -t initial_bundle.js.gz` must report OK
  3. Compare the .gz checksum/size against a known-good build to spot truncation
  4. Rebuild in a clean environment (fresh clone, adequate disk space) to rule out cache/transfer corruption

Example fix

# before: corrupted embedded asset
$ curl localhost:8080/.well-known/appsec/initial_bundle.js
# error: decompress initial bundle: unexpected EOF
# after
go generate ./pkg/appsec/challenge/... && make build
Defensive patterns

Strategy: try-catch

Validate before calling

if !bytes.HasPrefix(initialBundleGz, []byte{0x1f, 0x8b}) {
    return errors.New("embedded bundle is not gzip")
}
if zr, err := gzip.NewReader(bytes.NewReader(initialBundleGz)); err == nil {
    if _, err := io.ReadAll(zr); err != nil { return fmt.Errorf("truncated bundle: %w", err) }
}

Try / catch

bundle, err := challenge.InitialBundle()
if err != nil {
    log.Error().Err(err).Msg("embedded bundle decompression failed; rebuild required")
    http.Error(w, "bundle unavailable", http.StatusInternalServerError)
    return
}

Prevention

When it happens

Trigger: initialBundleGz passes gzip.NewReader's header check but its deflate stream is truncated or bit-flipped — e.g. a partial file was embedded because go:generate was interrupted or the asset was corrupted in the repo/build.

Common situations: Interrupted go:generate leaving a half-written .gz; LFS or git-smudge/clean filters corrupting binary assets; flaky CI artifact transfers; disk-full during the generate step.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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