caddyserver/caddy · error
quality too low; must be >=
Error message
quality too low; must be >= %d
What it means
Validation guard in Gzip.Validate: the configured gzip quality/level is below gzip.StatelessCompression, the minimum allowed value. The faulty input is the `level` set on the gzip encode handler in the JSON config; it must be >= the stateless-compression floor and <= BestCompression.
Solutions
- Set level within [-2, 9] (gzip.StatelessCompression..gzip.BestCompression); omit it to use the default
- Remember gzip levels are not zstd's speed names — use numbers only
Example fix
// before
{"level": -3}
// after
{"level": 5} Defensive patterns
Strategy: validation
Validate before calling
// before applying config
if lvl < -2 || lvl > 9 { return fmt.Errorf("gzip level out of range: %d", lvl) } Prevention
- Remember gzip range is -2..9
- Omit level to use Caddy's default
When it happens
Trigger: {"level": -3} in the gzip encoder config, or a Caddyfile/JSON value that unmarshalates to a number < -2.
Common situations: Copy-pasting level values from other software (zstd/brotli use different ranges); negative numbers intended as 'no compression' set too low.
Related errors
- quality too high; must be <=
- encoding is duplicated in prefer
- encoding not enabled
- unexpected compression level, use one of
- automation policy is the second policy that acts as…
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/475cfe5a68011031.
Report an issue: GitHub.
Appendix: source
Thrown at modules/caddyhttp/encode/gzip/gzip.go:71
if err != nil {
return err
}
g.Level = level
return nil
}
// Provision provisions g's configuration.
func (g *Gzip) Provision(ctx caddy.Context) error {
if g.Level == 0 {
g.Level = defaultGzipLevel
}
return nil
}
// Validate validates g's configuration.
func (g Gzip) Validate() error {
if g.Level < gzip.StatelessCompression {
return fmt.Errorf("quality too low; must be >= %d", gzip.StatelessCompression)
}
if g.Level > gzip.BestCompression {
return fmt.Errorf("quality too high; must be <= %d", gzip.BestCompression)
}
return nil
}
// AcceptEncoding returns the name of the encoding as
// used in the Accept-Encoding request headers.
func (Gzip) AcceptEncoding() string { return "gzip" }
// NewEncoder returns a new gzip writer.
func (g Gzip) NewEncoder() encode.Encoder {
writer, _ := gzip.NewWriterLevel(nil, g.Level)
return writer
}
// Informed from http://blog.klauspost.com/gzip-performance-for-go-webservers/View on GitHub (pinned to 50e54ee279)