{"record":{"id":"1b7a0f33932f02fa","repo":"nats-io/nats-server","slug":"error-reading-compression-reader-w-1b7a0f","errorCode":null,"errorMessage":"error reading compression reader: %w","messagePattern":"error reading compression reader: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/ocsp_responsecache.go","lineNumber":366,"sourceCode":"\tinput := bytes.NewReader(buf[:bodyLen])\n\tif n, err := io.CopyN(writer, input, bodyLen); err != nil {\n\t\treturn nil, fmt.Errorf(certidp.ErrCannotWriteCompressed, err)\n\t} else if n != bodyLen {\n\t\treturn nil, fmt.Errorf(certidp.ErrTruncatedWrite, n, bodyLen)\n\t}\n\tif err := writer.Close(); err != nil {\n\t\treturn nil, fmt.Errorf(certidp.ErrCannotCloseWriter, err)\n\t}\n\treturn output.Bytes(), nil\n}\n\nfunc (c *LocalCache) Decompress(buf []byte) ([]byte, error) {\n\tbodyLen := int64(len(buf))\n\tinput := bytes.NewReader(buf[:bodyLen])\n\treader := io.NopCloser(s2.NewReader(input))\n\toutput, err := io.ReadAll(reader)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(certidp.ErrCannotReadCompressed, err)\n\t}\n\treturn output, reader.Close()\n}\n\nfunc (c *LocalCache) loadCache(s *Server) {\n\td := s.opts.OCSPCacheConfig.LocalStore\n\tif d == _EMPTY_ {\n\t\td = OCSPResponseCacheDefaultDir\n\t}\n\tf := OCSPResponseCacheDefaultFilename\n\tstore, err := filepath.Abs(path.Join(d, f))\n\tif err != nil {\n\t\ts.Errorf(certidp.ErrLoadCacheFail, err)\n\t\treturn\n\t}\n\ts.Debugf(certidp.DbgLoadingCache, store)\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/ocsp_responsecache.go#L348-L384","documentation":"This error is returned by LocalCache.Decompress when reading from the s2 reader fails during io.ReadAll, meaning the cached OCSP response bytes are not valid s2-compressed data or are corrupted. It is wrapped with certidp.ErrCannotReadCompressed and surfaced to Get callers so the corrupt entry can be treated as a miss rather than served.","triggerScenarios":"LocalCache.Get -> Decompress where the stored bytes were not produced by Compress, were truncated on disk, or the s2 stream has a bad checksum/block header causing io.ReadAll to fail.","commonSituations":"Manual edits or corruption of the local cache directory; entries written by a different compression format/version; disk truncation after a crash; a plaintext response loaded into a compressed cache slot.","solutions":["Delete the corrupt entry (or the whole local cache directory) so Get re-fetches and re-compresses a fresh response.","Verify entries were written by the same Compress implementation/format version that Decompress expects.","Confirm the on-disk file length matches the recorded bodyLen; re-store if truncated.","Log the wrapped s2 error to identify whether it is a header or checksum failure before retrying."],"exampleFix":"// before\noutput, err := io.ReadAll(reader)\nif err != nil {\n\treturn nil, fmt.Errorf(certidp.ErrCannotReadCompressed, err)\n}\n// after\noutput, err := io.ReadAll(reader)\nif err != nil {\n\t// treat as cache miss so caller re-fetches instead of failing\n\treturn nil, fmt.Errorf(\"%w: %v (corrupt cache entry, evicting)\", certidp.ErrCannotReadCompressed, err)\n}","handlingStrategy":"fallback","validationCode":"// on Get: detect non-s2 data before Decompress\nif n, ok := s2.DecodedLen(buf); !ok || n <= 0 {\n\treturn nil, ErrCorruptCacheEntry\n}","typeGuard":null,"tryCatchPattern":"data, err := cache.Decompress(raw)\nif err != nil {\n\tlog.Printf(\"corrupt cache entry, refetching: %v\", err)\n\treturn fetchAndStore() // fallback to origin\n}","preventionTips":["Evict and refetch on any Decompress error instead of serving the entry.","Keep the Compress/Decompress format version in the entry header.","Periodically validate cache files on disk for truncation."],"tags":["compression","io","cache","corruption"],"backgroundTag":"corrupt-cache-entry","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}