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
- Add a case for the missing Domain constant in the switch in TxnNamedRead.read()
- Verify the TxnNamedRead was constructed/serialized with a supported domain (Key or Range)
- Check for version skew between nodes — upgrade the cluster so all nodes agree on the Domain enum
- 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 adding a Domain constant, grep for switch statements over Domain and update all of them
- Keep exhaustive switch dispatch (no shared default) so compilers flag missing cases
- Test transaction reads for every Domain value in CI
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
- Unhandled domain
- Unsupported domain
- accord.cache_size option was set incorrectly to
- accord.journal_directory must be specified
- accord.journal_directory must not be the same as any…
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)