{"record":{"id":"f3bd3445f68c2afd","repo":"apache/cassandra","slug":"compression-exception","errorCode":null,"errorMessage":"Compression exception","messagePattern":"Compression exception","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/compress/CompressedSequentialWriter.java","lineNumber":216,"sourceCode":"    }\n\n    @Override\n    protected void flushData()\n    {\n        // resetAndTruncate leaves fchannel.position() past EOF after its verification reads + truncate;\n        // re-seek so the next chunk lands at chunkOffset. No-op under linear writes.\n        seekToChunkStart();\n\n        try\n        {\n            // compressing data with buffer re-use\n            buffer.flip();\n            compressed.clear();\n            compressor.compress(buffer, compressed);\n        }\n        catch (IOException e)\n        {\n            throw new RuntimeException(\"Compression exception\", e); // shouldn't happen\n        }\n\n        int uncompressedLength = buffer.position();\n        int compressedLength = compressed.position();\n        uncompressedSize += uncompressedLength;\n        ByteBuffer toWrite = compressed;\n        if (compressedLength >= maxCompressedLength)\n        {\n            toWrite = buffer;\n            if (uncompressedLength >= maxCompressedLength)\n            {\n                compressedLength = uncompressedLength;\n            }\n            else\n            {\n                // Pad the uncompressed data so that it reaches the max compressed length.\n                // This could make the chunk appear longer, but this path is only reached at the end of the file, where\n                // we use the file size to limit the buffer on reading.","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/compress/CompressedSequentialWriter.java#L198-L234","documentation":"While flushing a data chunk, CompressedSequentialWriter compresses the buffer via ICompressor.compress(). Compression is expected to be in-memory and infallible, so an IOException from the compressor is wrapped in a bare RuntimeException(\"Compression exception\") — the comment notes it 'shouldn't happen'. Hitting it means the compressor implementation genuinely failed.","triggerScenarios":"flushData() invoking compressor.compress(buffer, compressed) on a chunk where the compressor implementation throws IOException — e.g. a buggy or custom ICompressor implementation, corrupted native compression library state (LZ4/Snappy/Deflate JNI), or an output buffer sized incorrectly for the compressed output.","commonSituations":"Custom or third-party compression implementations plugged into Cassandra; native library (liblz4/libsnappy) mismatches after upgrades; JVM transitions between native and pure-Java compressor variants.","solutions":["Inspect the wrapped IOException cause to identify which compressor failed and why","Switch the compression algorithm on the table to a well-tested default (LZ4Compressor or SnappyCompressor) and rebuild/flush the affected SSTables","Verify native library versions match the Cassandra build; force the Java implementation if the JNI library is suspect","If a custom ICompressor is installed, fix its compress() contract (output buffer sizing, error handling) and add unit tests"],"exampleFix":"// before\nCREATE TABLE ks.tbl (...) WITH compression = {'class': 'MyCustomCompressor'}; // buggy compress()\n// after\nALTER TABLE ks.tbl WITH compression = {'class': 'LZ4Compressor'};\nnodetool scrub ks tbl;","handlingStrategy":"try-catch","validationCode":"// Sanity-check compressor roundtrip before relying on a custom implementation\nByteBuffer in = ByteBuffer.allocate(chunkSize);\nByteBuffer out = ByteBuffer.allocate(compressor.initialCompressedBufferLength(chunkSize));\ncompressor.compress(in, out); // must not throw for well-formed input","typeGuard":null,"tryCatchPattern":"try {\n    flushData();\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"Compression exception\")) {\n        // inspect e.getCause() (IOException) — switch table compression to a standard impl and rebuild\n    }\n}","preventionTips":["Stick to built-in compressors (LZ4, Snappy, Deflate) in production","Unit-test any custom ICompressor for the full compress/uncompress roundtrip at chunk sizes","Keep native compression libraries in sync with the Cassandra version; fall back to Java impls if JNI fails"],"tags":["compression","compressed-writer","io","invariant"],"backgroundTag":"compression-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}