apache/cassandra · error · IOException

Corrupt (negative) clustering value length encountered: ${le

Error message

Corrupt (negative) clustering value length encountered: ${length}

What it means

validateClusteringValueLength rejects a negative length read from disk for a clustering value. A negative length cannot be a valid encoded size, so the bytes are corrupt and an IOException is thrown; callers wrap it in CorruptSSTableException.

Source

Thrown at src/java/org/apache/cassandra/io/sstable/SSTableCursorReader.java:1105

        validateClusteringValueLength(varLength);
        clustering.writeUnsignedVInt(varLength);
        clustering.loadPart(dataReader, varLength);
        return 0;
    }

    /**
     * Rejects a clustering value length the wire cannot have produced honestly. Both checks mirror
     * AbstractType.read, the reference for this format. readUnsignedVInt32 can return a negative
     * int, which is why the first check exists: an unchecked negative length reaches
     * {@link java.io.DataInput#skipBytes} as a silent no-op, and a buffer sizer as a defect.
     *
     * <p>Every caller of this walk wraps it and reports a {@code CorruptSSTableException}.
     */
    @VisibleForTesting
    static void validateClusteringValueLength(int length) throws IOException
    {
        if (length < 0)
            throw new IOException("Corrupt (negative) clustering value length encountered: " + length);
        if (length > DatabaseDescriptor.getMaxValueSize())
            throw new IOException(String.format("Corrupt clustering value length %d encountered, as it exceeds the maximum of %d, " +
                                                "which is set via max_value_size in cassandra.yaml",
                                                length, DatabaseDescriptor.getMaxValueSize()));
    }

    private static void skipClustering(RandomAccessReader dataReader, AbstractType<?>[] types, int clusteringColumnsBound) throws IOException
    {
        long clusteringBlockHeader = 0;
        for (int clusteringIndex = 0; clusteringIndex < clusteringColumnsBound; clusteringIndex++)
        {
            // struct clustering_block {
            //    varint clustering_block_header;
            //    simple_cell[] clustering_cells;
            // };
            if (clusteringIndex % 32 == 0)
            {
                clusteringBlockHeader = dataReader.readUnsignedVInt();

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Run nodetool verify / sstableverify to confirm corruption.
  2. Run nodetool scrub (sstablescrub) to salvage or quarantine the affected sstable.
  3. Restore the file from backup and run nodetool repair to restore replication consistency.
  4. If reads are misaligned, fix the preceding deserialization code so offsets stay correct.

Example fix

// before
int len = in.readUnsignedShort();
skipClustering(in, types, len);
// after
int len = in.readUnsignedShort();
validateClusteringValueLength(len); // throws on negative/oversized before use
skipClustering(in, types, len);
Defensive patterns

Strategy: try-catch

Validate before calling

if (length < 0) throw new IOException("negative clustering length: " + length);

Try / catch

try {
    value = readClusteringValue(in);
} catch (IOException e) {
    if (e.getMessage().contains("Corrupt"))
        throw new CorruptSSTableException(e, filename);
    throw e;
}

Prevention

When it happens

Trigger: Deserializing/skipping clustering values where the on-disk length prefix decodes to a negative int — corrupted sstable bytes or misaligned reads following earlier corruption.

Common situations: Disk/bit-flip corruption; sstables truncated or written by a buggy writer; cursor misalignment after a prior deserialization bug.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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