apache/cassandra · error · IOException

Invalid large Columns subset: missing count ${encoded} of ${

Error message

Invalid large Columns subset: missing count ${encoded} of ${supersetCount}

What it means

UnfilteredDescriptor.readLargeColumnsSubset decodes a 'large' Columns subset as an unsigned vint 'missing count' delta (supersetCount - presentCount). If the encoded missing count exceeds the superset column count the value cannot be valid, so the reader throws IOException ('Invalid large Columns subset: missing count N of M') indicating corrupt or misaligned sstable bytes (src/java/org/apache/cassandra/io/sstable/UnfilteredDescriptor.java:190).

Source

Thrown at src/java/org/apache/cassandra/io/sstable/UnfilteredDescriptor.java:190

        // Mirrors the corruption check in Columns.Serializer.deserializeSubset.
        if ((encoded >>> rowColumns.size()) != 0)
            throw new IOException("Invalid Columns subset bytes; too many bits set: " + Long.toBinaryString(encoded));
        missingColumnsMask = encoded;
    }

    /**
     * Wire format per Columns.Serializer.serializeLargeSubset: an unsigned vint delta of
     * supersetCount - presentCount, then one unsigned vint superset index per column. The indices
     * name the present columns when presentCount is under half the superset, and the missing
     * columns otherwise. Decoding into reusable mask words leaves rowColumns as the superset, so
     * CellCursor never rebuilds its per-superset arrays.
     */
    private void readLargeColumnsSubset(RandomAccessReader dataReader) throws IOException
    {
        long encoded = dataReader.readUnsignedVInt();
        int supersetCount = rowColumns.size();
        if (encoded > supersetCount)
            throw new IOException("Invalid large Columns subset: missing count " + encoded + " of " + supersetCount);

        int delta = (int) encoded;
        int columnCount = supersetCount - delta;
        int nWords = (supersetCount + 63) >>> 6;
        if (presentColumnsWords == null || presentColumnsWords.length < nWords)
            presentColumnsWords = new long[nWords];

        if (columnCount < supersetCount / 2)
            readPresentColumnIndexes(dataReader, supersetCount, nWords, columnCount);
        else
            readMissingColumnIndexes(dataReader, supersetCount, nWords, delta);

        useColumnsWords = true;
        missingColumnsMask = 0;
    }

    private void readPresentColumnIndexes(RandomAccessReader dataReader, int supersetCount, int nWords, int columnCount) throws IOException
    {

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Run nodetool verify/scrub on the keyspace to detect and remove the corrupt sstable
  2. Restore the damaged sstable from snapshot/backup or run repair so other replicas rebuild the lost ranges
  3. Check disk health for the data directory and replace failing hardware
  4. Verify the sstable format matches the running Cassandra version; re-upgrade or replay sstables via nodetool upgradesstables if versions mismatch

Example fix

// before
long encoded = reader.readUnsignedVInt();
int missing = (int) encoded; // may exceed superset, corrupt mask built silently
// after
if (encoded > supersetCount)
    throw new IOException("Invalid large Columns subset: missing count " + encoded + " of " + supersetCount);
int missing = (int) encoded;
Defensive patterns

Strategy: try-catch

Validate before calling

long encoded = dataReader.readUnsignedVInt();
if (encoded > rowColumns.size())
    throw new IOException("corrupt large columns subset: " + encoded);

Try / catch

try {
    readLargeColumnsSubset(reader);
} catch (IOException e) {
    // mark table corrupt, run scrub/repair from replicas
}

Prevention

When it happens

Trigger: Reading an sstable descriptor block where the large-subset unsigned vint decodes to a missing-count greater than rowColumns.size(): corruption at that offset, reading at the wrong file position, truncation followed by re-read of stale bytes, or a format/version mismatch between writer and reader.

Common situations: Failing disks producing bit-rot in sstable files; incomplete file copies or restores that shift offsets; nodes upgraded/downgraded across sstable format versions reading files they shouldn't; streaming interrupted sstables being opened.

Related errors


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