apache/cassandra · error · IllegalStateException

Unhandled domain

Error message

Unhandled domain {domain}

What it means

TxnNamedRead.read() dispatches a local read based on the Domain of the read's key. Accord transactions only support Domain.Key and Domain.Range reads; any other Domain value reaches the default branch, indicating an unhandled or newly added Domain that this code path does not implement.

Solutions

  1. Add a case for the missing Domain constant in the switch in TxnNamedRead.read()
  2. Verify the TxnNamedRead was constructed/serialized with a supported domain (Key or Range)
  3. Check for version skew between nodes — upgrade the cluster so all nodes agree on the Domain enum
  4. Confirm the command passed in is a SinglePartitionReadCommand (Key) or PartitionRangeReadCommand (Range) as expected

Example fix

// before
default:
    throw new IllegalStateException("Unhandled domain " + key.domain());
// after
case RangeSlice:
    return performLocalRangeSliceRead(executor, command, key.asRange(), consistencyLevel, nowInSeconds);
default:
    throw new IllegalStateException("Unhandled domain " + key.domain());
Defensive patterns

Strategy: validation

Validate before calling

if (!EnumSet.of(Domain.Key, Domain.Range).contains(namedRead.key().domain()))
    throw new IllegalArgumentException("Read domain must be Key or Range: " + namedRead.key().domain());

Type guard

static boolean hasSupportedDomain(TxnNamedRead read) {
    Domain d = read.key().domain();
    return d == Domain.Key || d == Domain.Range;
}

Try / catch

try { read = namedRead.read(executor, ...); }
catch (IllegalStateException e) { /* unsupported domain — log domain and fail the txn */ }

Prevention

When it happens

Trigger: Calling TxnNamedRead.read() with a TxnNamedRead whose key domain is neither Key nor Range — typically after a new Domain enum constant is added to Accord or a corrupted/malformed serialized TxnNamedRead supplies an unexpected domain.

Common situations: Developers extending the Domain enum in the Accord integration without updating the read dispatch; deserializing transaction data from a newer/older Cassandra version with different Domain values; internal invariant breakage in transaction setup.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/service/accord/txn/TxnNamedRead.java:250

    {
        ReadCommand command = deserialize(tables);
        if (command == null)
            return AsyncChains.success(new TxnData());

        // It's fine for our nowInSeconds to lag slightly our insertion timestamp, as to the user
        // this simply looks like the transaction witnessed TTL'd data and the data then expired
        // immediately after the transaction executed, and this simplifies things a great deal
        long nowInSeconds = nowInSeconds(executeAt);

        boolean withoutReconciliation = readsWithoutReconciliation(consistencyLevel);
        switch (key.domain())
        {
            case Key:
                return performLocalKeyRead(executor, ((SinglePartitionReadCommand) command).withTransactionalSettings(withoutReconciliation, nowInSeconds));
            case Range:
                return performLocalRangeRead(executor, ((PartitionRangeReadCommand) command), key.asRange(), consistencyLevel, nowInSeconds);
            default:
                throw new IllegalStateException("Unhandled domain " + key.domain());
        }
    }

    public TxnNamedRead slice(Range range)
    {
        Invariants.require(key.domain().isRange());
        if (key.equals(range))
            return this;

        Invariants.require(((Range)key).contains(range));
        return new TxnNamedRead(txnDataName(), range, unsafeBytes());
    }

    public TxnNamedRead merge(TxnNamedRead with)
    {
        Invariants.require(key.domain().isRange());
        if (key.equals(with.key))
            return this;

View on GitHub (pinned to 88fd0f6a0e)