apache/cassandra · critical · CorruptSSTableException

CorruptSSTableException wrapping IOException for ${path}

Error message

CorruptSSTableException wrapping IOException for ${path}

What it means

SSTableIdentityIterator.create() reads a partition's rows from an SSTable data file. If any IOException occurs while parsing the file, the sstable is marked suspect and the IOException is wrapped in a CorruptSSTableException carrying the file path. This is Cassandra's standard signal that the on-disk SSTable data could not be read or is structurally damaged.

Source

Thrown at src/java/org/apache/cassandra/io/sstable/SSTableIdentityIterator.java:82

    {
        return create(sstable, sstable.metadata(), file, key);
    }

    public static SSTableIdentityIterator create(SSTableReader sstable, TableMetadata tableMetadata, RandomAccessReader file, DecoratedKey key)
    {
        try
        {
            DeletionTime partitionLevelDeletion = DeletionTime.getSerializer(sstable.descriptor.version).deserialize(file);
            if (!partitionLevelDeletion.validate())
                UnfilteredValidation.handleInvalid(tableMetadata, key, sstable, "partitionLevelDeletion="+partitionLevelDeletion.toString());
            DeserializationHelper helper = new DeserializationHelper(tableMetadata, sstable.descriptor.version.correspondingMessagingVersion(), DeserializationHelper.Flag.LOCAL);
            SSTableSimpleIterator iterator = SSTableSimpleIterator.create(tableMetadata, file, sstable.header, helper, partitionLevelDeletion);
            return new SSTableIdentityIterator(sstable, key, partitionLevelDeletion, file.getPath(), iterator);
        }
        catch (IOException e)
        {
            sstable.markSuspect();
            throw new CorruptSSTableException(e, file.getPath());
        }
        catch (CorruptSSTableException e) // to ensure that we marked the sstable as suspected if CorruptSSTableException is thrown from lower levels
        {
            sstable.markSuspect();
            throw e;
        }
    }

    public static SSTableIdentityIterator create(SSTableReader sstable, FileDataInput dfile, long dataPosition, DecoratedKey key, boolean tombstoneOnly)
    {
        return create(sstable, sstable.metadata(), dfile, dataPosition, key, tombstoneOnly);
    }

    public static SSTableIdentityIterator create(SSTableReader sstable, TableMetadata tableMetadata, FileDataInput dfile, long dataPosition, DecoratedKey key, boolean tombstoneOnly)
    {
        try
        {
            dfile.seek(dataPosition);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Identify the file from the exception path and run `nodetool scrub` (or `sstablesplit`/verify tools) on the table so corrupt data is discarded or repaired
  2. Restore the affected SSTables from a backup or repair the replica via `nodetool repair` so a good copy is streamed from another node
  3. Check dmesg / system logs for disk errors and replace failing hardware before restarting the node
  4. Verify the Cassandra version that wrote the sstable matches the reading version; use upgradesstables after version upgrades

Example fix

// before: repeatedly restarting node without handling corruption
// after: detect and scrub the corrupt table
nodetool scrub -- keyspace table
# or restore from backup / run: nodetool repair -- keyspace table
Defensive patterns

Strategy: try-catch

Validate before calling

// before reading, verify sstable components exist and pass checksum validation
// sstableverify / sstablemetadata can detect corruption up front
if (!new File(path + '-Data.db').exists()) throw new IllegalStateException('missing sstable');

Try / catch

try {
    iter = SSTableIdentityIterator.create(meta, sstable, key, file, deletion);
} catch (CorruptSSTableException e) {
    logger.error("Corrupt sstable {}: {}", e.getPath(), e.getCause());
    // trigger scrub/repair, exclude sstable from reads
}

Prevention

When it happens

Trigger: Calling SSTableIdentityIterator.create(tableMetadata, sstable, key, file, partitionLevelDeletion) when the underlying data file throws an IOException during SSTableSimpleIterator parsing: truncated file, bad read from a compressed or uncompressed RandomAccessReader, or I/O failure from the disk during iteration setup.

Common situations: Hardware or disk failure corrupting an SSTable; manually copied or truncated SSTable files; files transferred without schema compatibility (e.g. upgrading between incompatible versions); filesystem-level corruption; reading an sstable whose compression metadata is missing or mismatched.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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