apache/cassandra · error · RuntimeException

Unable to append merkle tree hash to result

Error message

Unable to append merkle tree hash to result

What it means

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.

Solutions

  1. Treat as a JVM-level bug: capture the full stack trace and inspect the cause chain of the RuntimeException
  2. Verify no custom OutputStream or security manager wraps byte-array writes
  3. Retry the hash computation; if reproducible, report with the Cassandra version and repair context
  4. Refactor locally to use baos.toByteArray()-based APIs or write(byte[],int,int) that does not declare IOException

Example fix

// before
try { baos.write(n.hash()); } catch (IOException e) { throw new RuntimeException("Unable to append merkle tree hash to result"); }
// after
baos.write(n.hash(), 0, n.hash().length); // ByteArrayOutputStream.write(byte[]) never throws IOException
Defensive patterns

Strategy: try-catch

Try / catch

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; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/c2751ea47f9eeb01. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/utils/MerkleTrees.java:316

        }
    }

    @VisibleForTesting
    public byte[] hash(Range<Token> range)
    {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
        {
            boolean hashed = false;

            for (Map.Entry<Range<Token>, MerkleTree> entry : merkleTrees.entrySet())
                if (entry.getKey().intersects(range))
                    hashed |= entry.getValue().ifHashesRange(range, n -> baos.write(n.hash()));

            return hashed ? baos.toByteArray() : null;
        }
        catch (IOException e)
        {
            throw new RuntimeException("Unable to append merkle tree hash to result");
        }
    }

    /**
     * Get an iterator of all ranges and their MerkleTrees.
     */
    public Iterator<Map.Entry<Range<Token>, MerkleTree>> iterator()
    {
        return merkleTrees.entrySet().iterator();
    }

    public long rowCount()
    {
        long totalCount = 0;
        for (MerkleTree tree : merkleTrees.values())
        {
            totalCount += tree.rowCount();
        }

View on GitHub (pinned to 88fd0f6a0e)