{"record":{"id":"a5bd78fda21e9c29","repo":"JuliusBrussee/caveman","slug":"gzip-close-w","errorCode":null,"errorMessage":"gzip close: %w","messagePattern":"gzip close: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/objectstore/compress.go","lineNumber":46,"sourceCode":"\n// DefaultMaxDecompressedBytes protects callers that do not have trusted size\n// metadata. Callers with an expected plaintext size should use\n// DecompressLimit with the smaller, metadata-validated limit.\nconst DefaultMaxDecompressedBytes int64 = 128 << 20\n\n// Compress encodes data with the named codec. \"none\" returns data unchanged.\nfunc Compress(codec string, data []byte) ([]byte, error) {\n\tswitch codec {\n\tcase CompressionNone, \"\":\n\t\treturn data, nil\n\tcase CompressionGzip:\n\t\tvar buf bytes.Buffer\n\t\tzw := gzip.NewWriter(&buf)\n\t\tif _, err := zw.Write(data); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"gzip: %w\", err)\n\t\t}\n\t\tif err := zw.Close(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"gzip close: %w\", err)\n\t\t}\n\t\treturn buf.Bytes(), nil\n\tcase CompressionZstd:\n\t\treturn zstdEnc.EncodeAll(data, nil), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown compression codec %q\", codec)\n\t}\n}\n\n// Decompress reverses Compress with a defensive default expansion ceiling. An\n// unknown codec fails closed.\nfunc Decompress(codec string, data []byte) ([]byte, error) {\n\treturn DecompressLimit(codec, data, DefaultMaxDecompressedBytes)\n}\n\n// DecompressLimit reverses Compress while refusing to produce more than\n// maxBytes of plaintext. The limit is applied while decoding gzip and through\n// zstd's decoder memory bound, so highly-compressible hostile payloads cannot","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/objectstore/compress.go#L28-L64","documentation":"Compress wrote the data into the gzip.Writer successfully but zw.Close() failed. Close flushes remaining buffered data and writes the gzip footer; a failure here means the compressed stream is incomplete and must not be used. The error is wrapped with \"gzip close: \" and Compress returns nil bytes.","triggerScenarios":"Calling objectstore.Compress with CompressionGzip where the underlying writer fails during flush/footer write on Close — again only realistic with a failing underlying writer, corruption, or resource exhaustion since the target is a bytes.Buffer.","commonSituations":"Rare in production; typically seen with injected failing writers in tests or after unusual memory-pressure conditions aborting the flush.","solutions":["Retry the compression; a transient close failure on an in-memory buffer should not persist.","Treat the returned nil output as authoritative — never fall back to partially-compressed data.","Inspect the wrapped cause; if persistent, verify library/binary integrity and memory limits.","In tests using a failing writer, confirm the failure is intentional and assert the error path.","For large inputs, confirm the process isn't hitting memory limits that could disrupt buffered writes."],"exampleFix":"// before\nout, err := objectstore.Compress(objectstore.CompressionGzip, data)\nif err != nil { return err } // out is nil, message lost\n// after\nout, err := objectstore.Compress(objectstore.CompressionGzip, data)\nif err != nil {\n    return fmt.Errorf(\"upload aborted: cannot produce compressed payload: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"out, err := objectstore.Compress(objectstore.CompressionGzip, data)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"gzip close:\") {\n        // stream incomplete: never use partial output (out is nil anyway); retry\n        out, err = objectstore.Compress(objectstore.CompressionGzip, data)\n    }\n    if err != nil {\n        return fmt.Errorf(\"gzip close failed, payload unusable: %w\", err)\n    }\n}","preventionTips":["Treat any compression error as 'no valid output' — never fall back to partial data.","Avoid wrapping the buffer in custom writers that can fail on Close.","Retry transient compression failures with a bounded retry count.","Watch memory pressure when compressing very large payloads."],"tags":["compression","gzip","go","objectstore"],"backgroundTag":"gzip-compression-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}