{"record":{"id":"3734f3b71892bb6d","repo":"apache/cassandra","slug":"insufficient-remaining-bytes-to-deserialize-a-leaf","errorCode":null,"errorMessage":"Insufficient remaining bytes to deserialize a Leaf node off-heap","messagePattern":"Insufficient remaining bytes to deserialize a Leaf node off-heap","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/utils/MerkleTree.java","lineNumber":1109,"sourceCode":"        {\n            int size = in.readByte();\n            switch (size)\n            {\n                case HASH_SIZE:\n                    byte[] hash = new byte[HASH_SIZE];\n                    in.readFully(hash);\n                    return new OnHeapLeaf(hash);\n                case 0:\n                    return new OnHeapLeaf();\n                default:\n                    throw new IllegalStateException(format(\"Hash of size %d encountered, expecting %d or %d\", size, HASH_SIZE, 0));\n            }\n        }\n\n        int serializeOffHeap(ByteBuffer buffer, IPartitioner p)\n        {\n            if (buffer.remaining() < OffHeapLeaf.maxOffHeapSize())\n                throw new IllegalStateException(\"Insufficient remaining bytes to deserialize a Leaf node off-heap\");\n\n            if (hash.length != HASH_SIZE)\n                throw new IllegalArgumentException(\"Hash of unexpected size when serializing a Leaf off-heap: \" + hash.length);\n\n            final int position = buffer.position();\n            buffer.put(hash);\n            return ~position;\n        }\n\n        @Override\n        public String toString()\n        {\n            return \"#<OnHeapLeaf \" + Node.toString(hash()) + '>';\n        }\n    }\n\n    static class OffHeapLeaf extends OffHeapNode implements Leaf\n    {","sourceCodeStart":1091,"sourceCodeEnd":1127,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/utils/MerkleTree.java#L1091-L1127","documentation":"OffHeapLeaf.serializeOffHeap writes a fixed-size (maxOffHeapSize) slot into the target ByteBuffer. If the buffer has fewer remaining bytes than that maximum, it throws IllegalStateException('Insufficient remaining bytes to deserialize a Leaf node off-heap') — a caller precondition failure, since the caller must reserve enough space before asking for serialization.","triggerScenarios":"Calling OffHeapLeaf.serializeOffHeap(ByteBuffer, IPartitioner) with a buffer whose remaining() is less than OffHeapLeaf.maxOffHeapSize(); i.e., the off-heap region or buffer slice allocated for the node is too small.","commonSituations":"MerkleTree off-heap serialization with a mis-sized allocated buffer; bugs in size accounting when laying out the tree into off-heap memory; custom code reusing the internal serializer with its own buffer.","solutions":["Size the destination buffer to at least OffHeapLeaf.maxOffHeapSize() before serializing","Use MerkleTree's own off-heap sizing helpers (MerkleTree.HEAP_SIZE / comparable utilities) to compute the required allocation","Check buffer.position()/limit() math for off-by-one or accumulated offsets","If encountered during normal repair, upgrade — it indicates an internal size-accounting bug"],"exampleFix":"// before\nByteBuffer buf = ByteBuffer.allocateDirect(leaf.hash.length);\nleaf.serializeOffHeap(buf, partitioner);\n// after\nByteBuffer buf = ByteBuffer.allocateDirect(OffHeapLeaf.maxOffHeapSize());\nleaf.serializeOffHeap(buf, partitioner);","handlingStrategy":"validation","validationCode":"// Java: precondition check before calling serializeOffHeap\nif (buffer.remaining() < OffHeapLeaf.maxOffHeapSize()) {\n    throw new IllegalArgumentException(\"Need \" + OffHeapLeaf.maxOffHeapSize() + \" bytes, have \" + buffer.remaining());\n}\nleaf.serializeOffHeap(buffer, partitioner);","typeGuard":"static boolean canSerializeLeaf(ByteBuffer buf) {\n    return buf != null && buf.remaining() >= OffHeapLeaf.maxOffHeapSize();\n}","tryCatchPattern":"try {\n    leaf.serializeOffHeap(buffer, partitioner);\n} catch (IllegalStateException e) {\n    logger.error(\"Off-heap leaf serialization failed: {}\", e.getMessage());\n    throw new IllegalStateException(\"Under-allocated off-heap buffer for MerkleTree\", e);\n}","preventionTips":["Size buffers from OffHeapLeaf.maxOffHeapSize() (and Inner equivalents), not from hash length","Track cumulative offsets when laying out whole trees off-heap","Assert remaining() before each node write in custom serialization","Let MerkleTree manage its own off-heap allocation instead of custom buffers"],"tags":["merkle-tree","off-heap","buffer"],"backgroundTag":"internal-invariant-violation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}