{"record":{"id":"996646c23b4a6c96","repo":"apache/cassandra","slug":"another-sequence-of-kind-kind-is-in-progress-fo-996646","errorCode":null,"errorMessage":"Another sequence of kind ${kind} is in progress for node ${nodeIpOrId}. Cannot proceed with force join.","messagePattern":"Another sequence of kind (.+?) is in progress for node (.+?)\\. Cannot proceed with force join\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tools/CMSOfflineTool.java","lineNumber":663,"sourceCode":"            NodeId nodeId = nodeIdentifierOption.getNodeId(metadata);\n            Set<Token> tokenSet = new HashSet<>(tokens.size());\n            Token.TokenFactory tokenFactory = metadata.partitioner.getTokenFactory();\n            tokens.forEach(t -> tokenSet.add(tokenFactory.fromString(t)));\n\n            NodeState nodeState = metadata.directory.peerState(nodeId);\n            if (nodeState == NodeState.JOINED)\n            {\n                throw new IllegalArgumentException(\"Node \" + nodeIdentifierOption.getNodeIpOrId() +\n                                                   \" is already in JOINED state.\");\n            }\n\n            ClusterMetadata updatedMetadata;\n            if (metadata.inProgressSequences.get(nodeId) != null)\n            {\n                MultiStepOperation<?> multiStepOperation = metadata.inProgressSequences.get(nodeId);\n                if (multiStepOperation.kind() != MultiStepOperation.Kind.JOIN)\n                {\n                    throw new IllegalArgumentException(\"Another sequence of kind \" + multiStepOperation.kind() +\n                                                       \" is in progress for node \" + nodeIdentifierOption.getNodeIpOrId() +\n                                                       \". Cannot proceed with force join.\");\n                }\n                BootstrapAndJoin bootstrapAndJoin = (BootstrapAndJoin) multiStepOperation;\n                Set<Token> sequenceTokens = bootstrapAndJoin.finishJoin.tokens;\n                if (tokens.isEmpty()\n                    || (tokenSet.size() == sequenceTokens.size() && sequenceTokens.containsAll(tokenSet)))\n                {\n                    updatedMetadata = bootstrapAndJoin.applyTo(metadata).success().metadata;\n                }\n                else\n                {\n                    // If tokens are provided, then it should match with the in-progress sequence tokens\n                    throw new IllegalArgumentException(\"The tokens provided \" + tokens + \" do not match with \" +\n                                                       \" in progress BootstrapAndJoin sequence tokens \" +\n                                                       sequenceTokens + \". Cannot proceed further.\");\n                }\n            }","sourceCodeStart":645,"sourceCodeEnd":681,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tools/CMSOfflineTool.java#L645-L681","documentation":"Thrown by ForceJoin when the node already has an in-progress MultiStepOperation whose kind is not JOIN. Concurrent sequences (e.g. decommission, replace) cannot be bypassed by a force join, so the tool refuses to proceed.","triggerScenarios":"Force-joining a node that has an in-progress sequence of a non-JOIN kind in metadata.inProgressSequences, such as an active decommission or move sequence recorded in the metadata snapshot.","commonSituations":"A decommission/rebuild was interrupted and left its sequence recorded; operator tries force join as a recovery shortcut without finishing or cancelling the other operation first.","solutions":["Complete or cancel the other in-progress sequence first (e.g. finish the decommission offline).","Verify the intended node: the sequence may belong to a different host than you meant.","Edit/discard the stale metadata only if you understand the consequences of dropping the sequence."],"exampleFix":"// before\n// forceJoin on node with inProgressSequences[nodeId] = DecommissionSequence\n// after\n// complete/cancel the decommission sequence, then forceJoin","handlingStrategy":"validation","validationCode":"MultiStepOperation<?> op = metadata.inProgressSequences.get(nodeId);\nif (op != null && op.kind() != MultiStepOperation.Kind.JOIN)\n    throw new IllegalStateException(\"Finish/cancel \" + op.kind() + \" first\");","typeGuard":null,"tryCatchPattern":"try { forceJoin(...); } catch (IllegalArgumentException e) { logger.error(\"Conflicting sequence: \" + e.getMessage()); }","preventionTips":["Resolve pending sequences before forcing joins","Audit inProgressSequences in the metadata snapshot","Only use force join as a last-resort recovery"],"tags":["cluster-metadata","multi-step-operation","conflicting-operation"],"backgroundTag":"conflicting-config-options","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"}