{"record":{"id":"c2751ea47f9eeb01","repo":"apache/cassandra","slug":"unable-to-append-merkle-tree-hash-to-result","errorCode":null,"errorMessage":"Unable to append merkle tree hash to result","messagePattern":"Unable to append merkle tree hash to result","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/utils/MerkleTrees.java","lineNumber":316,"sourceCode":"        }\n    }\n\n    @VisibleForTesting\n    public byte[] hash(Range<Token> range)\n    {\n        try (ByteArrayOutputStream baos = new ByteArrayOutputStream())\n        {\n            boolean hashed = false;\n\n            for (Map.Entry<Range<Token>, MerkleTree> entry : merkleTrees.entrySet())\n                if (entry.getKey().intersects(range))\n                    hashed |= entry.getValue().ifHashesRange(range, n -> baos.write(n.hash()));\n\n            return hashed ? baos.toByteArray() : null;\n        }\n        catch (IOException e)\n        {\n            throw new RuntimeException(\"Unable to append merkle tree hash to result\");\n        }\n    }\n\n    /**\n     * Get an iterator of all ranges and their MerkleTrees.\n     */\n    public Iterator<Map.Entry<Range<Token>, MerkleTree>> iterator()\n    {\n        return merkleTrees.entrySet().iterator();\n    }\n\n    public long rowCount()\n    {\n        long totalCount = 0;\n        for (MerkleTree tree : merkleTrees.values())\n        {\n            totalCount += tree.rowCount();\n        }","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/utils/MerkleTrees.java#L298-L334","documentation":"MerkleTrees.hash() serializes tree hashes through a ByteArrayOutputStream whose write() declares IOException, though in-memory byte arrays never actually throw it. The catch block rethrows any IOException as this RuntimeException. It effectively signals an unexpected I/O failure while appending hash bytes to the result buffer.","triggerScenarios":"Any IOException thrown while calling baos.write(n.hash()) inside MerkleTrees.hash() — practically only from wrapped/custom OutputStream-like logic or future API changes, since ByteArrayOutputStream.write cannot fail in the JDK.","commonSituations":"Seen in repair validator completion (testValidatorComplete) or hash extraction (mt2hash) when hashed range traversal writes fail; nearly always indicates an unexpected JVM/stream-level problem rather than a user error.","solutions":["Treat as a JVM-level bug: capture the full stack trace and inspect the cause chain of the RuntimeException","Verify no custom OutputStream or security manager wraps byte-array writes","Retry the hash computation; if reproducible, report with the Cassandra version and repair context","Refactor locally to use baos.toByteArray()-based APIs or write(byte[],int,int) that does not declare IOException"],"exampleFix":"// before\ntry { baos.write(n.hash()); } catch (IOException e) { throw new RuntimeException(\"Unable to append merkle tree hash to result\"); }\n// after\nbaos.write(n.hash(), 0, n.hash().length); // ByteArrayOutputStream.write(byte[]) never throws IOException\n","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { byte[] h = trees.hash(range); } catch (RuntimeException e) { if (e.getMessage().contains(\"Unable to append merkle tree hash\")) { logger.error(\"hash computation failed\", e); /* retry or abort repair */ } else throw e; }","preventionTips":["Keep JVM/OS-level stream errors out of scope: this is effectively unreachable, so treat any occurrence as a bug report","Retry hash computation once before failing the repair session","Log the full cause chain for diagnostics","Avoid wrapping ByteArrayOutputStream usage with custom throwing streams"],"tags":["merkle-tree","hashing","runtime-exception"],"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"}