apache/cassandra · warning

Error reading partition

Error message

Error reading partition %s (stacktrace follows):

What it means

While scrubbing a BTI sstable, reading a partition from the data file threw an unexpected (non-fatal) exception. The scrubber logs this warning with the partition key and full stacktrace, then attempts recovery: if the index is still usable it seeks to the next indexed partition position and retries reading the partition once from the correct offset.

Solutions

  1. Review the logged stacktrace to identify the corruption type (IO vs deserialization).
  2. Let scrub finish — bad partitions are counted and skipped or retried; then compact to rebuild.
  3. Run `nodetool repair` (or full/repaired-datanote-based repair) so replicas restore missing data.
  4. Check storage health and replace failing disks; restore from snapshot if corruption is severe.

Example fix

// Operational recovery flow:
// before: scrub warns 'Error reading partition <key>'
// after:
$ nodetool scrub <keyspace> <table>
$ nodetool repair <keyspace> <table>
Defensive patterns

Strategy: try-catch

Validate before calling

// Detect bad sstable ahead of scrub using offline validation
$ sstableverify keyspace table   # or nodetool verify after node up

Try / catch

// Wrap scrub-triggering maintenance in monitoring of badPartitions output
OutputHandler handler = new OutputHandler.LogOutput();
// after scrub: inspect ScrubResult/badPartitions and alert if > 0

Prevention

When it happens

Trigger: `nodetool scrub` encounters an unreadable/undecodable partition in the data file — malformed partition header, corrupt row data, truncated file, or deserialization failure while reading the partition at dataStart.

Common situations: Disk corruption or bit-rot on Data.db; crash during compaction leaving half-written partitions; hardware faults; sstables copied while Cassandra was writing them.

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/0968be3d31b25182. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/io/sstable/format/bti/BtiTableScrubber.java:193

                if (currentIndexKey != null && !key.getKey().equals(currentIndexKey))
                {
                    throw new IOError(new IOException(String.format("Key from data file (%s) does not match key from index file (%s)",
                                                                    ByteBufferUtil.bytesToHex(key.getKey()), ByteBufferUtil.bytesToHex(currentIndexKey))));
                }

                if (indexIterator != null && dataSizeFromIndex > dataFile.length())
                    throw new IOError(new IOException("Impossible partition size (greater than file length): " + dataSizeFromIndex));

                if (indexIterator != null && dataStart != dataStartFromIndex)
                    outputHandler.warn("Data file partition position %d differs from index file row position %d", dataStart, dataStartFromIndex);

                if (tryAppend(prevKey, key, writer))
                    prevKey = key;
            }
            catch (Throwable th)
            {
                throwIfFatal(th);
                outputHandler.warn(th, "Error reading partition %s (stacktrace follows):", keyName);

                if (currentIndexKey != null
                    && (key == null || !key.getKey().equals(currentIndexKey) || dataStart != dataStartFromIndex))
                {

                    // position where the row should start in a data file (right after the partition key)
                    long rowStartFromIndex = dataStartFromIndex + TypeSizes.SHORT_SIZE + currentIndexKey.remaining();
                    outputHandler.output("Retrying from partition index; data is %s bytes starting at %s",
                                         dataSizeFromIndex, rowStartFromIndex);
                    key = sstable.decorateKey(currentIndexKey);
                    try
                    {
                        if (!isIndex)
                            partitionKeyType.validate(key.getKey());
                        dataFile.seek(rowStartFromIndex);

                        if (tryAppend(prevKey, key, writer))
                            prevKey = key;

View on GitHub (pinned to 88fd0f6a0e)