{"record":{"id":"2b9bc356dbce1c6f","repo":"apache/cassandra","slug":"cannot-transition-from-contains-to-any-other-state","errorCode":null,"errorMessage":"Cannot transition from CONTAINS to any other state.","messagePattern":"Cannot transition from CONTAINS to any other state\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/commitlog/CommitLogSegment.java","lineNumber":694,"sourceCode":"    }\n\n    /**\n     * Change the current cdcState on this CommitLogSegment. There are some restrictions on state transitions and this\n     * method is idempotent.\n     *\n     * @return the old cdc state\n     */\n    public CDCState setCDCState(CDCState newState)\n    {\n        if (newState == cdcState)\n            return cdcState;\n\n        // Also synchronized in CDCSizeTracker.processNewSegment and .processDiscardedSegment\n        synchronized(cdcStateLock)\n        {\n            // Need duplicate CONTAINS to be idempotent since 2 threads can race on this lock\n            if (cdcState == CDCState.CONTAINS && newState != CDCState.CONTAINS)\n                throw new IllegalArgumentException(\"Cannot transition from CONTAINS to any other state.\");\n\n            if (cdcState == CDCState.FORBIDDEN && newState != CDCState.PERMITTED)\n                throw new IllegalArgumentException(\"Only transition from FORBIDDEN to PERMITTED is allowed.\");\n\n            CDCState oldState = cdcState;\n            cdcState = newState;\n            return oldState;\n        }\n    }\n\n    /**\n     * A simple class for tracking information about the portion of a segment that has been allocated to a log write.\n     */\n    protected static class Allocation\n    {\n        private final CommitLogSegment segment;\n        private final OpOrder.Group appendOp;\n        private final int position;","sourceCodeStart":676,"sourceCodeEnd":712,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/commitlog/CommitLogSegment.java#L676-L712","documentation":"CommitLogSegment.setCDCState enforces CDC state machine rules: once a segment is CONTAINS (holds CDC-indexed data), it may never leave that state — CONTAINS->CONTAINS is idempotent, any other target throws IllegalArgumentException. This guarantees CDC data in a segment is never un-tracked.","triggerScenarios":"Calling setCDCState with a state other than CONTAINS while cdcState == CDCState.CONTAINS, e.g. trying to reset a completed segment to PERMITTED/FORBIDDEN, or racing callers that recompute state after the segment became CONTAINS.","commonSituations":"Custom CDC tooling manipulating segment states; tests simulating CDC transitions; races between CDCSizeTracker.processNewSegment and allocation-time state setting.","solutions":["Treat CONTAINS as terminal: only call setCDCState(CONTAINS) for such segments.","Check segment.getCDCState() before requesting a transition.","If you need a segment without CDC data, create a new segment rather than demoting an existing one.","Use the race-safe idempotent path: re-requesting CONTAINS on a CONTAINS segment is allowed."],"exampleFix":"// before\nsegment.setCDCState(CDCState.PERMITTED); // segment already CONTAINS\n// after\nif (segment.getCDCState() != CDCState.CONTAINS)\n    segment.setCDCState(CDCState.PERMITTED);","handlingStrategy":"validation","validationCode":"if (segment.getCDCState() == CDCState.CONTAINS && newState != CDCState.CONTAINS)\n    throw new IllegalArgumentException(\"CONTAINS is terminal for CDC state\");","typeGuard":null,"tryCatchPattern":"try {\n    segment.setCDCState(newState);\n} catch (IllegalArgumentException e) {\n    logger.warn(\"Illegal CDC transition on segment {}: {}\", segment, e.getMessage());\n}","preventionTips":["Treat CONTAINS as a terminal CDC state","Read getCDCState() before requesting any transition","Let CommitLog/CDCSizeTracker drive state changes instead of manual calls"],"tags":["commitlog","cdc","state-machine"],"backgroundTag":"invalid-state-transition","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"}