{"record":{"id":"6e9038fa613af21b","repo":"apache/cassandra","slug":"bad-cms-state","errorCode":null,"errorMessage":"Bad CMS state: ","messagePattern":"Bad CMS state: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/ClusterMetadataService.java","lineNumber":1090,"sourceCode":"        public Processor delegate()\n        {\n            return delegateInternal().right;\n        }\n\n        private Pair<State, Processor> delegateInternal()\n        {\n            State state = cmsStateSupplier.get();\n            switch (state)\n            {\n                case LOCAL:\n                case RESET:\n                    return Pair.create(state, local);\n                case REMOTE:\n                    return Pair.create(state, remote);\n                case GOSSIP:\n                    return Pair.create(state, gossip);\n            }\n            throw new IllegalStateException(\"Bad CMS state: \" + state);\n        }\n\n        @Override\n        public Commit.Result commit(Entry.Id entryId, Transformation transform, Epoch lastKnown, Retry retryPolicy)\n        {\n            while (true)\n            {\n                try\n                {\n                    Pair<State, Processor> delegate = delegateInternal();\n                    Commit.Result result = delegate.right.commit(entryId, transform, lastKnown, retryPolicy);\n                    ClusterMetadataService.State state = delegate.left;\n                    if (state == LOCAL || state == RESET)\n                        replicator.send(result, null);\n                    return result;\n                }\n                catch (NotCMSException e)\n                {","sourceCodeStart":1072,"sourceCodeEnd":1108,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/ClusterMetadataService.java#L1072-L1108","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nswitch (cmsStateSupplier.get())\n{\n    case RESET:\n    case LOCAL:\n        return Pair.create(state, local);\n    case REMOTE:\n        return Pair.create(state, remote);\n    case GOSSIP:\n        return Pair.create(state, gossip);\n}\nthrow new IllegalStateException(\"Bad CMS state: \" + state);\n// after (add the missing case as soon as a new state exists)\nswitch (cmsStateSupplier.get())\n{\n    case RESET:\n    case LOCAL:\n        return Pair.create(state, local);\n    case REMOTE:\n        return Pair.create(state, remote);\n    case GOSSIP:\n        return Pair.create(state, gossip);\n    case NEW_STATE:\n        return Pair.create(state, newStateProcessor);\n}\nthrow new IllegalStateException(\"Bad CMS state: \" + state);","handlingStrategy":"validation","validationCode":"CMSState state = ClusterMetadataService.instance.getState();\nSet<CMSState> known = EnumSet.of(CMSState.RESET, CMSState.LOCAL, CMSState.REMOTE, CMSState.GOSSIP);\nif (!known.contains(state)) throw new IllegalStateException(\"Unsupported CMS state \" + state);","typeGuard":"boolean isKnownState = (CMSState s) -> s == CMSState.RESET || s == CMSState.LOCAL || s == CMSState.REMOTE || s == CMSState.GOSSIP;","tryCatchPattern":"try\n{\n    commitViaPath(path, entryId, transform, lastKnown, retry);\n}\ncatch (IllegalStateException e)\n{\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Bad CMS state:\"))\n        throw new AssertionError(\"Internal bug: unhandled CMSState — report with full state\", e);\n    throw e;\n}","preventionTips":["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"],"tags":["tcm","internal-state","invariant","switch","enum"],"backgroundTag":"internal-invariant-violation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}