apache/cassandra · critical · RuntimeException

Cannot get comparator

Error message

Cannot get comparator %s in %s. This might due to a mismatch between the schema and the data read

What it means

CompositeType.getComparator(i) indexes into the composite's configured type list; if the serialized composite has more components than the current type list, IndexOutOfBoundsException is caught and rethrown as this RuntimeException. It signals that the on-disk composite was written under a different (older) schema than the one now being used to read it (CASSANDRA-6262).

Solutions

  1. Restore the original schema (re-add the removed composite types) so the data matches
  2. Rewrite the affected SSTables (e.g. scrub/upgrade or REWRITE) under the current schema
  3. Verify with sstablemetadata/sstabledump that the composite layout matches the schema
  4. Restore from a backup taken before the schema change
Defensive patterns

Strategy: try-catch

Try / catch

try { type.getComparator(i); } catch (RuntimeException e) { if (e.getMessage().startsWith("Cannot get comparator")) { /* schema/data mismatch: restore schema or rewrite sstables */ } else throw e; }

Prevention

When it happens

Trigger: Reading a cell whose composite value has more parts than types.size() after the CompositeType definition was altered (e.g. columns dropped or the comparator redefined); calling getComparator(int i) with i beyond the type list.

Common situations: Schema changes to clustered-column comparators without rewriting SSTables; restoring snapshots under a modified schema; upgrades where the comparator definition drifted from data.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/db/marshal/CompositeType.java:202

    @Override
    public TypeSerializer<ByteBuffer> getSerializer()
    {
        return serializer;
    }

    protected <V> AbstractType<?> getComparator(int i, V value, ValueAccessor<V> accessor, int offset)
    {
        try
        {
            return types.get(i);
        }
        catch (IndexOutOfBoundsException e)
        {
            // We shouldn't get there in general we shouldn't construct broken composites
            // but there is a few cases where if the schema has changed since we created/validated
            // the composite, this will be thrown (see #6262). Those cases are a user error but
            // throwing a more meaningful error message to make understanding such error easier. .
            throw new RuntimeException("Cannot get comparator " + i + " in " + this + ". "
                                     + "This might due to a mismatch between the schema and the data read", e);
        }
    }

    protected <VL, VR> AbstractType<?> getComparator(int i, VL left, ValueAccessor<VL> accessorL, VR right, ValueAccessor<VR> accessorR, int offsetL, int offsetR)
    {
        return getComparator(i, left, accessorL, offsetL);
    }

    protected <V> AbstractType<?> getAndAppendComparator(int i, V value, ValueAccessor<V> accessor, StringBuilder sb, int offset)
    {
        return types.get(i);
    }

    @Override
    public <V> ByteSource asComparableBytes(ValueAccessor<V> accessor, V data, Version version)
    {
        if (data == null || accessor.isEmpty(data))

View on GitHub (pinned to 88fd0f6a0e)