apache/cassandra · error · IllegalStateException
Bad CMS state:
Error message
Bad CMS state:
What it means
The commit processor wrapper switches on the node's CMS state (RESET, LOCAL, REMOTE, GOSSIP) to pick which processor handles commits. If the CMSState enum holds a value not covered by the switch, this internal-invariant IllegalStateException is thrown. It should be unreachable in normal operation and usually indicates a new enum constant added without updating this switch.
Solutions
- Report as a bug with the full state string from the message and the Cassandra version
- Check for version skew / mixed-version cluster during rolling upgrades and align versions
- If running a custom build, update the switch statement to handle the new CMSState value
- Restart the node to clear in-memory state and re-verify with a standard build
Example fix
// before
switch (cmsStateSupplier.get())
{
case RESET:
case LOCAL:
return Pair.create(state, local);
case REMOTE:
return Pair.create(state, remote);
case GOSSIP:
return Pair.create(state, gossip);
}
throw new IllegalStateException("Bad CMS state: " + state);
// after (add the missing case as soon as a new state exists)
switch (cmsStateSupplier.get())
{
case RESET:
case LOCAL:
return Pair.create(state, local);
case REMOTE:
return Pair.create(state, remote);
case GOSSIP:
return Pair.create(state, gossip);
case NEW_STATE:
return Pair.create(state, newStateProcessor);
}
throw new IllegalStateException("Bad CMS state: " + state); Defensive patterns
Strategy: validation
Validate before calling
CMSState state = ClusterMetadataService.instance.getState();
Set<CMSState> known = EnumSet.of(CMSState.RESET, CMSState.LOCAL, CMSState.REMOTE, CMSState.GOSSIP);
if (!known.contains(state)) throw new IllegalStateException("Unsupported CMS state " + state); Type guard
boolean isKnownState = (CMSState s) -> s == CMSState.RESET || s == CMSState.LOCAL || s == CMSState.REMOTE || s == CMSState.GOSSIP;
Try / catch
try
{
commitViaPath(path, entryId, transform, lastKnown, retry);
}
catch (IllegalStateException e)
{
if (e.getMessage() != null && e.getMessage().startsWith("Bad CMS state:"))
throw new AssertionError("Internal bug: unhandled CMSState — report with full state", e);
throw e;
} Prevention
- When adding CMSState constants, update every switch (enable -Xlint or exhaustive-switch checks)
- Treat this exception as a bug report, not a runtime condition to handle in production
- Run the TCM unit tests after touching ClusterMetadataService/CMSState
- Avoid custom builds diverging from upstream enum definitions in mixed clusters
When it happens
Trigger: Committing a transformation via the CMS-state-dispatching Commit.Path when ClusterMetadataService.state resolves to an unhandled CMSState value — practically only after a code change adds a new CMSState constant or corrupted in-memory state.
Common situations: Running a patched/custom Cassandra build where a new CMS state was added; upgrade skew where different code paths disagree on states; otherwise a genuine internal bug report.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Could not remove from CMS
- Failed to find endpoints to fetch
- Failed to find first CMS node in directory
- Illegal state:
- Addresses differ: !=
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/6e9038fa613af21b.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/tcm/ClusterMetadataService.java:1090
public Processor delegate()
{
return delegateInternal().right;
}
private Pair<State, Processor> delegateInternal()
{
State state = cmsStateSupplier.get();
switch (state)
{
case LOCAL:
case RESET:
return Pair.create(state, local);
case REMOTE:
return Pair.create(state, remote);
case GOSSIP:
return Pair.create(state, gossip);
}
throw new IllegalStateException("Bad CMS state: " + state);
}
@Override
public Commit.Result commit(Entry.Id entryId, Transformation transform, Epoch lastKnown, Retry retryPolicy)
{
while (true)
{
try
{
Pair<State, Processor> delegate = delegateInternal();
Commit.Result result = delegate.right.commit(entryId, transform, lastKnown, retryPolicy);
ClusterMetadataService.State state = delegate.left;
if (state == LOCAL || state == RESET)
replicator.send(result, null);
return result;
}
catch (NotCMSException e)
{View on GitHub (pinned to 88fd0f6a0e)