{"record":{"id":"d070dcc1c6ce2aff","repo":"apache/cassandra","slug":"corrupted-sstable-invalid-flags-found-deserializi","errorCode":null,"errorMessage":"Corrupted sstable. Invalid flags found deserializing DeletionTime: \" + Integer.toBinaryString(flags & 0xFF)","messagePattern":"Corrupted sstable\\. Invalid flags found deserializing DeletionTime: \" \\+ Integer\\.toBinaryString\\(flags & 0xFF\\)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"critical","filePath":"src/java/org/apache/cassandra/db/DeletionTime.java","lineNumber":256,"sourceCode":"        public void serialize(DeletionTime delTime, DataOutputPlus out) throws IOException\n        {\n            if (delTime == LIVE || delTime.isLive())\n                out.writeByte(IS_LIVE_DELETION);\n            else\n            {\n                // The sign bit is zero here, so we can write a long directly\n                out.writeLong(delTime.markedForDeleteAt());\n                out.writeInt(delTime.localDeletionTimeUnsignedInteger);\n            }\n        }\n\n        public DeletionTime deserialize(DataInputPlus in) throws IOException\n        {\n            int flags = in.readByte();\n            if ((flags & IS_LIVE_DELETION) != 0)\n            {\n                if ((flags & 0xFF) != IS_LIVE_DELETION)\n                    throw new IOException(\"Corrupted sstable. Invalid flags found deserializing DeletionTime: \" + Integer.toBinaryString(flags & 0xFF));\n                return LIVE;\n            }\n            else\n            {\n                // Read the remaining 7 bytes\n                int bytes1 = in.readByte();\n                int bytes2 = in.readShort();\n                int bytes4 = in.readInt();\n\n                long mfda = readBytesToMFDA(flags, bytes1, bytes2, bytes4);\n                int localDeletionTimeUnsignedInteger = in.readInt();\n\n                return new ImmutableDeletionTime(mfda, localDeletionTimeUnsignedInteger);\n            }\n        }\n\n        public void deserialize(DataInputPlus in, ReusableDeletionTime reuse) throws IOException\n        {","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/DeletionTime.java#L238-L274","documentation":"DeletionTime.Serializer.deserialize(DataInputPlus) reads a one-byte flags field from the wire. The top bit (IS_LIVE_DELETION) marks a live (non-deleted) DeletionTime; if it is set but any of the other 7 bits are also set, the encoding is not a valid live marker, so the deserializer throws an IOException declaring the sstable corrupted. This guards against reading data written by incompatible versions or truncated/corrupted files.","triggerScenarios":"Reading a Memtable/SSTable-backed partition or an index entry (IndexedEntry), or test/testE2EDeSerializeDT deserialization paths, where the byte read at the DeletionTime position has bit 0x80 set together with other bits (e.g. flags != 0x80). Caused by byte-stream misalignment, corruption, or a writer producing a malformed encoding.","commonSituations":"Bit-flip disk corruption or truncation of SSTable files; hand-crafted or corrupted commitlog/memtable data; reading sstables produced by a broken build or different Cassandra version with a changed on-wire format; failed reads surfaced via CorruptSSTableException wrappers in logs.","solutions":["Run `nodetool scrub` (or `sstablescrub`) on the affected table to repair or drop the corrupted sstable.","Verify disk/RAM health (smartctl, fsck) and restore the affected sstables from a backup or by rebuilding via repair (`nodetool repair`) from replicas.","Check that all nodes run compatible Cassandra versions and that no partial writes (e.g. from a crash during compaction) remain; delete leftover temp sstables.","Reproduce with the DeletionTime serializer unit tests to confirm the flags encoding on your build is 0x80 for live deletions."],"exampleFix":"// before: blindly deserializing a possibly-corrupt stream\nDeletionTime dt = DeletionTime.serializer.deserialize(in);\n// after: validate flags yourself and fail fast with context\nint flags = in.readByte();\nif ((flags & 0x80) != 0 && (flags & 0xFF) != 0x80)\n    throw new CorruptSSTableException(new IOException(\"Bad DeletionTime flags: \" + Integer.toBinaryString(flags & 0xFF)), file);","handlingStrategy":"try-catch","validationCode":"// before deserializing from an untrusted file, validate sstable integrity\nFile sstable = new File(path);\nif (!Digest.validate(sstable, digestFile)) throw new CorruptSSTableException(...);\n","typeGuard":"// check the flags byte yourself before full deserialize\nstatic boolean isValidDeletionTimeFlags(int flags) {\n    return (flags & 0x80) == 0 || (flags & 0xFF) == 0x80;\n}\n","tryCatchPattern":"try {\n    DeletionTime dt = DeletionTime.serializer.deserialize(in);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"Invalid flags found deserializing DeletionTime\"))\n        throw new CorruptSSTableException(e, sstableFile); // trigger repair/scrub\n    throw e;\n}\n","preventionTips":["Run `nodetool scrub` periodically and `nodetool repair` after disk incidents.","Use ECC RAM and monitor disk SMART health.","Keep all cluster nodes on the same, current Cassandra version.","Never hand-edit or truncate sstable files."],"tags":["sstable","corruption","serialization","io"],"backgroundTag":"checksum-mismatch","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"}