nats-io/nats-server · error
error closing compression writer: %w
Error message
error closing compression writer: %w
What it means
This error wraps a failure to Close the s2 compression writer in LocalCache.Compress. s2 writers buffer data and only flush the final compressed block on Close, so a Close error means the compressed output is incomplete/unusable. The library refuses to return bytes that could be a corrupt cache entry.
Source
Thrown at server/ocsp_responsecache.go:355
c.stats.Revokes++
case ocsp.Unknown:
c.stats.Unknowns++
}
}
}
func (c *LocalCache) Compress(buf []byte) ([]byte, error) {
bodyLen := int64(len(buf))
var output bytes.Buffer
writer := s2.NewWriter(&output)
input := bytes.NewReader(buf[:bodyLen])
if n, err := io.CopyN(writer, input, bodyLen); err != nil {
return nil, fmt.Errorf(certidp.ErrCannotWriteCompressed, err)
} else if n != bodyLen {
return nil, fmt.Errorf(certidp.ErrTruncatedWrite, n, bodyLen)
}
if err := writer.Close(); err != nil {
return nil, fmt.Errorf(certidp.ErrCannotCloseWriter, err)
}
return output.Bytes(), nil
}
func (c *LocalCache) Decompress(buf []byte) ([]byte, error) {
bodyLen := int64(len(buf))
input := bytes.NewReader(buf[:bodyLen])
reader := io.NopCloser(s2.NewReader(input))
output, err := io.ReadAll(reader)
if err != nil {
return nil, fmt.Errorf(certidp.ErrCannotReadCompressed, err)
}
return output, reader.Close()
}
func (c *LocalCache) loadCache(s *Server) {
d := s.opts.OCSPCacheConfig.LocalStore
if d == _EMPTY_ {View on GitHub (pinned to 3a66a489d2)
Solutions
- Check the error returned by writer.Close() and discard output.Bytes() — do not cache partial output.
- Ensure Close is called exactly once per writer and after all writes complete.
- Retry the compression of the same body once; s2 over bytes.Buffer should be deterministic.
- If reproducible, update/replace the s2 library version or disable compression for this entry.
Example fix
// before
if err := writer.Close(); err != nil {
return nil, fmt.Errorf(certidp.ErrCannotCloseWriter, err)
}
// after
if err := writer.Close(); err != nil {
return nil, fmt.Errorf("error closing compression writer: %w (discarding %d compressed bytes)", err, output.Len())
} Defensive patterns
Strategy: try-catch
Try / catch
compressed, err := cache.Compress(body)
if err != nil {
var trunc *certidp.ErrTruncatedWrite
switch {
case errors.As(err, &trunc):
// discard partial output, retry once
default:
log.Printf("compress failed: %v", err)
}
return err
} Prevention
- Call s2 writer Close exactly once, after all writes.
- Check Close's error before trusting output.Bytes().
- Retry deterministic compression once on transient failure.
When it happens
Trigger: LocalCache.Put -> Compress where s2.Writer.Close() returns a non-nil error, typically because an underlying write to the bytes.Buffer failed or internal s2 state is inconsistent.
Common situations: Underlying writer failure while flushing the final block; calling Close twice or using the writer after Close; panics/OOM inside the compressor surfaced at Close.
Related errors
- short write on body (%d != %d)
- error reading compression reader: %w
- error writing to compression writer: %w
- short write on body (%d != %d)
- error closing compression writer: %w
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/9bb0dd47db520268.
Report an issue: GitHub.