golang/go · error

gzip: invalid compression level: %d

Error message

gzip: invalid compression level: %d

What it means

`gzip.NewWriterLevel` validates that `level` is within `[HuffmanOnly(-2), BestCompression(9)]` before constructing the writer. Anything outside returns this error immediately — no writer is created. This is the public-API guard for gzip's compression level (it internally defers to flate).

Source

Thrown at src/compress/gzip/gzip.go:70

// exact written bytes.
func NewWriter(w io.Writer) *Writer {
	z, _ := NewWriterLevel(w, DefaultCompression)
	return z
}

// NewWriterLevel is like [NewWriter] but specifies the compression level instead
// of assuming [DefaultCompression].
//
// The compression level can be [DefaultCompression], [NoCompression], [HuffmanOnly]
// or any integer value between [BestSpeed] and [BestCompression] inclusive.
// The error returned will be nil if the level is valid.
//
// 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) {
	if level < HuffmanOnly || level > BestCompression {
		return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
	}
	z := new(Writer)
	z.init(w, level)
	return z, nil
}

func (z *Writer) init(w io.Writer, level int) {
	compressor := z.compressor
	if compressor != nil {
		compressor.Reset(w)
	}
	*z = Writer{
		Header: Header{
			OS: 255, // unknown
		},
		w:          w,
		level:      level,
		compressor: compressor,

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Clamp before constructing: `if level < gzip.HuffmanOnly { level = gzip.DefaultCompression } else if level > gzip.BestCompression { level = gzip.BestCompression }`.
  2. Use named constants from the gzip package instead of raw integers.
  3. If you only want the default, call `gzip.NewWriter(w)` (no level).

Example fix

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

Strategy: validation

Validate before calling

if level < gzip.HuffmanOnly || level > gzip.BestCompression {
    return nil, fmt.Errorf("gzip level %d out of range", level)
}

Try / catch

gw, err := gzip.NewWriterLevel(out, level)
if err != nil { level = gzip.DefaultCompression; gw, _ = gzip.NewWriterLevel(out, level) }

Prevention

When it happens

Trigger: Calling `gzip.NewWriterLevel(w, level)` with level < -2 or > 9; reading a level from config that uses a 1..12 or 0..100 scale; passing `gzip.DefaultCompression` (which is -1 and valid) versus a custom sentinel that resolves to e.g. 100.

Common situations: A `compression` knob in a settings file exposed without bounds; wrapping gzip behind an interface where the caller passes an unrelated integer; copy-pasting a zlib-style level (same range but the user misremembers as 0..10).

Related errors


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