apache/cassandra · error · IOException

Ballot file corrupted

Error message

Ballot file corrupted

What it means

After reading the two ballots from the ballot file, PaxosBallotTracker validates that the reader is at EOF and that the computed CRC32 matches the stored checksum. 'Ballot file corrupted' (IOException) means the file is truncated, has trailing bytes, or its contents don't match the checksum.

Source

Thrown at src/java/org/apache/cassandra/service/paxos/uncommitted/PaxosBallotTracker.java:113

        deleteIfExists(new File(directory, TMP_FNAME));

        File file = new File(directory, FNAME);
        if (!file.exists())
            return new PaxosBallotTracker(directory, Ballot.none(), Ballot.none());

        try (RandomAccessReader reader = RandomAccessReader.open(file))
        {
            int version = reader.readInt();
            if (version != FILE_VERSION)
                throw new IOException("Unsupported ballot file version: " + version);

            byte[] bytes = new byte[16];
            CRC32 crc = crc32();
            Ballot highBallot = deserializeBallot(reader, crc, bytes);
            Ballot lowBallot = deserializeBallot(reader, crc, bytes);
            int checksum = Integer.reverseBytes(reader.readInt());
            if (!reader.isEOF() || (int) crc.getValue() != checksum)
                throw new IOException("Ballot file corrupted");

            return new PaxosBallotTracker(directory, highBallot, lowBallot);
        }
    }

    private static void deleteIfExists(File file)
    {
        if (file.exists())
            file.delete();
    }

    public synchronized void flush() throws IOException
    {
        File file = new File(directory, TMP_FNAME);
        deleteIfExists(file);

        try(SequentialWriter writer = new SequentialWriter(file, FINISH_ON_CLOSE))
        {

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Stop the node and delete the corrupt ballot file so the tracker recreates it from current paxos state
  2. Verify disk health (smartctl/filesystem check) if corruption recurs
  3. Restore data directories only from consistent backups taken with the node stopped or via snapshots
  4. Take the file's checksum failure to the mailing list/JIRA if it reproduces across restarts

Example fix

// before
# node fails: Ballot file corrupted
// after
$ nodetool stop
$ rm /var/lib/cassandra/data/system/...-paxos_ballot.bin
$ restart node
Defensive patterns

Strategy: try-catch

Validate before calling

// integrity pre-check: size and CRC of the ballot file
File f = ballotFile;
if (!f.exists() || f.length() != expectedFileLength) { /* treat as missing/corrupt */ }

Try / catch

try { tracker = PaxosBallotTracker.load(dir); } catch (IOException e) { if (e.getMessage().equals("Ballot file corrupted")) { Files.delete(dir.resolve(BALLOT_FILE)); tracker = PaxosBallotTracker.load(dir); } else throw e; }

Prevention

When it happens

Trigger: Power loss or crash mid-write leaving a partially written ballot file; disk corruption; manual editing or truncation of the file; a file written by an incompatible version with same version id but different layout.

Common situations: Host crash/OOM-kill without clean shutdown, failing disks, restores from partial backups, or copying data directories while the node was running.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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