apache/cassandra · error · IllegalStateException

Can not advance in-progress sequence, since its kind is

Error message

Can not advance in-progress sequence, since its kind is %s, but not %s

What it means

Thrown by ReconfigureCMS.executeNext when the in-progress sequence under the ReconfigureCMS SequenceKey has a kind other than RECONFIGURE_CMS. executeNext advances the current step of the sequence; the kind check guards against advancing a foreign sequence as if it were a CMS reconfiguration.

Solutions

  1. Wait for the occupying sequence to complete before calling executeNext again
  2. Re-read ClusterMetadata.current() and confirm the sequence kind before advancing
  3. Serialize topology operations so only one multi-step sequence is in flight
  4. Investigate the metadata log if the key was reused across operation types
Defensive patterns

Strategy: validation

Validate before calling

MultiStepOperation<?> seq = ClusterMetadata.current().inProgressSequences.get(SequenceKey.instance);
if (seq == null || seq.kind() != MultiStepOperation.Kind.RECONFIGURE_CMS)
    return; // skip advance; wrong or absent sequence

Try / catch

try { reconfigureCMS.executeNext(); }
catch (IllegalStateException e) { if (e.getMessage().contains("Can not advance in-progress sequence")) revalidateAndRetry(); else throw e; }

Prevention

When it happens

Trigger: Invoking executeNext (e.g. to advance a CMS reconfiguration after a barrier) while the SequenceKey slot holds a different MultiStepOperation kind.

Common situations: Racing topology operations occupying the same SequenceKey; resuming a sequence after a partially applied log replay where the key was reused; automation calling executeNext without re-validating current metadata state.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/sequences/ReconfigureCMS.java:184

        ImmutableSet.Builder<MetadataKey> modifiedKeys = ImmutableSet.builder();
        while (metadata.inProgressSequences.contains(SequenceKey.instance))
        {
            ReconfigureCMS transitionCMS = (ReconfigureCMS) metadata.inProgressSequences.get(SequenceKey.instance);
            Transformation.Result result = transitionCMS.next.execute(metadata);
            assert result.isSuccess();
            metadata = result.success().metadata.forceEpoch(lastModifiedEpoch);
            modifiedKeys.addAll(result.success().affectedMetadata);
        }
        return new Transformation.Success(metadata.forceEpoch(lastModifiedEpoch.nextEpoch()), LockedRanges.AffectedRanges.EMPTY, modifiedKeys.build());
    }

    @Override
    public SequenceState executeNext()
    {
        ClusterMetadata metadata = ClusterMetadata.current();
        MultiStepOperation<?> sequence = metadata.inProgressSequences.get(SequenceKey.instance);
        if (sequence.kind() != MultiStepOperation.Kind.RECONFIGURE_CMS)
            throw new IllegalStateException(String.format("Can not advance in-progress sequence, since its kind is %s, but not %s", sequence.kind(), MultiStepOperation.Kind.RECONFIGURE_CMS));

        ReconfigureCMS transitionCMS = (ReconfigureCMS) sequence;
        try
        {
            if (transitionCMS.next.activeTransition != null)
            {
                // An active transition represents a joining member which has been added as a write replica, but must
                // stream up to date distributed log tables before being able to serve reads & participate in quorums.
                // If this is the case, do that streaming now.
                ActiveTransition activeTransition = transitionCMS.next.activeTransition;
                InetAddressAndPort endpoint = metadata.directory.endpoint(activeTransition.nodeId);
                Replica replica = new Replica(endpoint, entireRange, true);
                streamRanges(replica, activeTransition.streamCandidates(metadata.directory));
            }
            else
            {
                // Run a paxos repair before starting either the addition or removal of a CMS member, where in both
                // cases there is no active transition.

View on GitHub (pinned to 88fd0f6a0e)