apache/cassandra · error · IOException
Unsupported ballot file version
Error message
Unsupported ballot file version: ${version} What it means
PaxosBallotTracker persists high/low paxos ballots to a per-directory ballot file stamped with a FILE_VERSION. On load it throws IOException 'Unsupported ballot file version' when the file's version integer differs from the version this build writes — typically a file from a different Cassandra version or a corrupt/garbage first 4 bytes.
Solutions
- Stop the node and delete the ballot file (it is rebuilt from current paxos state; safe while no in-flight CAS relies on it — prefer deleting only when the directory is for a dropped/unsupported state)
- Confirm the running Cassandra version matches the version that wrote the files; complete a rolling upgrade/downgrade consistently
- Check disk/filesystem health if the version bytes look corrupted
- If caused by downgrade, use the officially supported downgrade procedure which handles state files
Example fix
// before cassandra$ cp -r /old/data /data # old-version ballot files mixed in // after cassandra$ rm /data/*/paxos_ballot* # or matching ballot tracker files $ .build/build-jars.sh -s && restart node
Defensive patterns
Strategy: validation
Validate before calling
// check the ballot file's version int before starting Cassandra
try (DataInputStream in = new DataInputStream(new FileInputStream(ballotFile))) {
int v = Integer.reverseBytes(in.readInt());
if (v != expectedFileVersion) { /* move file aside or confirm upgrade/downgrade path */ }
} Try / catch
try { PaxosBallotTracker.load(dir); } catch (IOException e) { if (e.getMessage().startsWith("Unsupported ballot file version")) { /* remove/rotate file, reload */ } throw e; } Prevention
- Never mix data directories across incompatible Cassandra versions
- Use the supported upgrade/downgrade procedure
- Back up ballot files only from the same version that will read them
- Watch for crash-truncated files after unclean shutdowns
When it happens
Trigger: Downgrading or upgrading Cassandra across versions that changed the ballot file format; a truncated or zero-filled ballot file left by a crash; the file being written by a different (patched) implementation.
Common situations: Rolling upgrades/downgrades where old ballot files remain in the data directories; restoring data dirs from backups taken with a different version; disk corruption.
Related errors
- Expected version 0 for unversioned serializer
- Unsupported SSTable version /
- Attempted skipBytes() on a closed RAR
- Attempted to seek in a closed RAR
- Attempted to use message version " + messagingVersion + "…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/51e1397223702d21.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/service/paxos/uncommitted/PaxosBallotTracker.java:105
{
logger.info("truncating paxos ballot metadata in {}", directory);
deleteIfExists(new File(directory, TMP_FNAME));
deleteIfExists(new File(directory, FNAME));
}
public static PaxosBallotTracker load(File directory) throws IOException
{
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();
}View on GitHub (pinned to 88fd0f6a0e)