crowdsecurity/crowdsec · error
gzip reader for initial bundle: %w
Error message
gzip reader for initial bundle: %w
What it means
The challenge runtime decompresses the embedded initial_bundle.js.gz at startup via a sync.Once; gzip.NewReader fails when the baked-in blob is not valid gzip data. The error is cached in initialBundleErr so every subsequent request for the bundle fails the same way. This almost always means the build artifact is broken, not runtime data.
Source
Thrown at pkg/appsec/challenge/static_bundle.go:58
// 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{
"compressed_bytes": len(initialBundleGz),
"decompressed_bytes": len(initialBundle),
"duration_ms": time.Since(decompressStart).Milliseconds(),
}).Debug("decompressed baked-in obfuscated challenge code")
})
View on GitHub (pinned to 909b515798)
Solutions
- Run `go generate` (or `make build`) to (re)create initial_bundle.js.gz, then rebuild the binary
- Inspect the embedded .gz file: `file initial_bundle.js.gz` and `gzip -t` to confirm it is valid gzip
- Clean the build cache / rebuild from a fresh checkout so a stale blob is not embedded
- Verify the build pipeline runs the generate step before `go build`
Example fix
// before: build without generated asset go build ./cmd/crowdsec // after go generate ./pkg/appsec/challenge/... go build ./cmd/crowdsec
Defensive patterns
Strategy: try-catch
Validate before calling
if len(initialBundleGz) == 0 || !bytes.HasPrefix(initialBundleGz, []byte{0x1f, 0x8b}) {
return errors.New("embedded initial bundle missing or not gzip")
} Try / catch
bundle, err := challenge.InitialBundle()
if err != nil {
log.Error().Err(err).Msg("embedded bundle broken; run go generate and rebuild")
http.Error(w, "bundle unavailable", http.StatusInternalServerError)
return
} Prevention
- Always build via `make build`, which runs go:generate
- Add `gzip -t` validation of the asset in CI before packaging
- Fail the build if initial_bundle.js.gz is missing or empty
- Avoid hand-editing or reformatting generated assets
When it happens
Trigger: The embedded initialBundleGz contains corrupt, empty-after-check, or non-gzip bytes — e.g. go:generate never ran, or a bad build pipeline stored a placeholder/HTML error page in the .gz file.
Common situations: Fresh checkout where `go generate ./pkg/appsec/challenge/...` was not run; CI builds the binary without the generate step; a partially-written or LFS-mishandled .gz asset; a stale build cache embedding an old broken blob.
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
- decompress initial bundle: %w
- failed to create gzip reader for obfuscator wasm: %w
- failed to decompress obfuscator wasm: %w
- esbuild returned no output files
- obfuscator produced empty output
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/e77329443f920837.
Report an issue: GitHub.