golang/go · error

zlib: invalid compression level: %d

Error message

zlib: invalid compression level: %d

What it means

`zlib.NewWriterLevel` (and `NewWriterLevelDict`) reject a `level` outside `[HuffmanOnly(-2), BestCompression(9)]` before constructing the writer. This mirrors gzip/flate; zlib wraps DEFLATE so the level range is identical.

Source

Thrown at src/compress/zlib/writer.go:78

// Note that the exact bytes written to w are not covered by the Go 1
// compatibility promise. Callers, including tests, should not depend on the
// exact written bytes.
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
	return NewWriterLevelDict(w, level, nil)
}

// NewWriterLevelDict is like [NewWriterLevel] but specifies a dictionary to
// compress with.
//
// The dictionary may be nil. If not, its contents should not be modified until
// the Writer is closed.
//
// Note that the exact bytes written to w are not covered by the Go 1
// compatibility promise. Callers, including tests, should not depend on the
// exact written bytes.
func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
	if level < HuffmanOnly || level > BestCompression {
		return nil, fmt.Errorf("zlib: invalid compression level: %d", level)
	}
	return &Writer{
		w:     w,
		level: level,
		dict:  dict,
	}, nil
}

// Reset clears the state of the [Writer] z such that it is equivalent to its
// initial state from [NewWriterLevel] or [NewWriterLevelDict], but instead writing
// to w.
func (z *Writer) Reset(w io.Writer) {
	z.w = w
	// z.level and z.dict left unchanged.
	if z.compressor != nil {
		z.compressor.Reset(w)
	}
	if z.digest != nil {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Clamp into range using the zlib constants (`zlib.DefaultCompression`, `zlib.BestSpeed`, `zlib.BestCompression`, `zlib.HuffmanOnly`).
  2. If unsure, use `zlib.DefaultCompression` (-1).
  3. Validate config-supplied integers at load time and reject with a clear message.

Example fix

// before
zw, err := zlib.NewWriterLevel(out, 12)
// after
zw, err := zlib.NewWriterLevel(out, zlib.BestCompression)
Defensive patterns

Strategy: validation

Validate before calling

if level < zlib.HuffmanOnly || level > zlib.BestCompression {
    level = zlib.DefaultCompression
}

Try / catch

zw, err := zlib.NewWriterLevel(out, level)
if err != nil { zw = zlib.NewWriter(out) /* fall back to default */ }

Prevention

When it happens

Trigger: Calling `zlib.NewWriterLevel(w, level)` with level < -2 or > 9; plumbing a config value on a different scale; passing the `zlib` level where a `flate` constant of a different numbering was intended (same range, but easy to mix).

Common situations: Settings files exposing a `level` field without bounds; defaulting to 0 thinking it means BestSpeed (0 is actually NoCompression/Store for flate-backed zlib — valid, but surprising — whereas the invalid values are < -2 or > 9).

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/19a6a5e871a0b0e6. Report an issue: GitHub.