apache/cassandra · error · IllegalStateException

Unhandled type

Error message

Unhandled type {type}

What it means

The TxnRead.serializer's skip() reads a one-byte type tag from the wire and dispatches on it. Only TYPE_EMPTY_KEY, TYPE_EMPTY_RANGE and TYPE_NOT_EMPTY are valid; any other byte means the stream is corrupt or was written by an incompatible serializer version, so an IllegalStateException is thrown.

Solutions

  1. Verify all nodes run a compatible Cassandra version (serialization format skew)
  2. Check for stream corruption / message framing bugs upstream of this deserializer
  3. Add a case for the unexpected type byte if a new type constant was intentionally introduced
  4. Enable tracing on inter-node messaging to find the sender producing bad payloads

Example fix

// before
default:
    throw new IllegalStateException("Unhandled type " + type);
// after
case TYPE_NOT_EMPTY_V2:
    skipArray(tablesAndKeys, in, version, TxnNamedRead.v2Serializer);
    return;
default:
    throw new IllegalStateException("Unhandled type " + type);
Defensive patterns

Strategy: try-catch

Validate before calling

byte type = peekTypeByte(payload);
if (type != TYPE_EMPTY_KEY && type != TYPE_EMPTY_RANGE && type != TYPE_NOT_EMPTY)
    throw new IOException("Corrupt TxnRead type tag: " + type);

Try / catch

try { serializer.skip(tablesAndKeys, in, version); }
catch (IllegalStateException e) { throw new IOException("Corrupt or version-skewed TxnRead payload", e); }

Prevention

When it happens

Trigger: Deserializing (skipping over) a TxnRead whose first byte is not one of the defined type constants — corrupt wire data, wrong serializer version, or misaligned read position in the input stream.

Common situations: Mixed-version cluster during upgrade where serialization formats differ; message corruption; a bug in a peer writing the type byte; manually crafted or fuzzed inter-node payloads.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/service/accord/txn/TxnRead.java:432

            if (read.items.length > 0)
            {
                out.write(TYPE_NOT_EMPTY);
                serializeArray(read.items, tablesAndKeys, out, version, TxnNamedRead.serializer);
                serializeNullable(read.cassandraConsistencyLevel, out, consistencyLevelSerializer);
            }
            else
            {
                out.write(read.domain == Domain.Key ? TYPE_EMPTY_KEY : TYPE_EMPTY_RANGE);
            }
        }

        public void skip(TableMetadatasAndKeys tablesAndKeys, DataInputPlus in, Version version) throws IOException
        {
            byte type = in.readByte();
            switch (type)
            {
                default:
                    throw new IllegalStateException("Unhandled type " + type);
                case TYPE_EMPTY_KEY:
                case TYPE_EMPTY_RANGE:
                    return;
                case TYPE_NOT_EMPTY:
                    skipArray(tablesAndKeys, in, version, TxnNamedRead.serializer);
                    deserializeNullable(in, consistencyLevelSerializer);
            }
        }


        @Override
        public TxnRead deserialize(TableMetadatasAndKeys tablesAndKeys, DataInputPlus in, Version version) throws IOException
        {
            byte type = in.readByte();
            switch (type)
            {
                default:
                    throw new IllegalStateException("Unhandled type " + type);

View on GitHub (pinned to 88fd0f6a0e)