{"record":{"id":"355b511eca33be69","repo":"apache/cassandra","slug":"can-t-do-any-consensus-migrations-to-from-paxosv1","errorCode":null,"errorMessage":"Can't do any consensus migrations to/from PaxosV1, switch to V2 first","messagePattern":"Can't do any consensus migrations to/from PaxosV1, switch to V2 first","errorType":"console","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/consensus/migration/ConsensusTableMigration.java","lineNumber":200,"sourceCode":"\n        if (keyspaceNames == null || keyspaceNames.isEmpty())\n        {\n            keyspaceNames = ImmutableList.copyOf(StorageService.instance.getNonLocalStrategyKeyspaces());\n        }\n        checkState(keyspaceNames.size() == 1 || !maybeTables.isPresent(), \"Can't specify tables with multiple keyspaces\");\n        List<TableId> ids = keyspacesAndTablesToTableIds(cm, keyspaceNames, maybeTables);\n\n        List<TableId> tableIds = new ArrayList<>();\n        for (TableId tableId : ids)\n        {\n            TableMetadata metadata = cm.schema.getTableMetadata(tableId);\n            if (metadata == null || !metadata.params.transactionalMigrationFrom.isMigrating())\n                continue;\n            tableIds.add(tableId);\n        }\n\n        if (!Paxos.useV2())\n            throw new IllegalStateException(\"Can't do any consensus migrations to/from PaxosV1, switch to V2 first\");\n\n        IPartitioner partitioner = DatabaseDescriptor.getPartitioner();\n        Optional<List<Range<Token>>> maybeParsedRanges = maybeRangesStr.map(rangesStr -> ImmutableList.copyOf(RepairOption.parseRanges(rangesStr, partitioner)));\n        Token minToken = partitioner.getMinimumToken();\n        NormalizedRanges<Token> ranges = normalizedRanges(maybeParsedRanges.orElse(ImmutableList.of(new Range(minToken, minToken))));\n\n        ClusterMetadataService.instance().commit(new BeginConsensusMigrationForTableAndRange(ranges, tableIds));\n    }\n\n    public static Integer finishMigrationToConsensusProtocol(@Nonnull String keyspace,\n                                                             @Nonnull Optional<List<String>> maybeTables,\n                                                             @Nonnull Optional<String> maybeRangesStr,\n                                                             @Nonnull ConsensusMigrationTarget target)\n    {\n        checkArgument(!maybeTables.isPresent() || !maybeTables.get().isEmpty(), \"Must provide at least 1 table if Optional is not empty\");\n        checkNotNull(target);\n        ClusterMetadata cm = ClusterMetadata.current();\n","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/consensus/migration/ConsensusTableMigration.java#L182-L218","documentation":"Consensus (Paxos) migration can only be performed when Paxos V2 is in use. If a node has paxos_variant set to v1 (or the legacy default), starting a migration to any consensus protocol throws this IllegalStateException, because V1 semantics are incompatible with migration state transitions.","triggerScenarios":"Calling startMigrationToConsensusProtocol (e.g. via ALTER TABLE ... WITH transactional_migration or the migration tooling) while Paxos.useV2() is false — i.e. the cluster/node is configured with paxos_variant=v1 or unset on a version where V2 is not the default.","commonSituations":"Upgrading an old cluster where paxos_variant was explicitly pinned to v1 in cassandra.yaml; mixed-version cluster during rolling upgrade before all nodes support V2; operator forgetting to switch to V2 before initiating Accord/migration.","solutions":["Set paxos_variant: v2 in cassandra.yaml on all nodes and restart them (rolling restart is fine)","Verify with a node check that Paxos V2 is active, then retry the migration command","Complete any pending Paxos V1 state (all in-flight LWTs drained) before switching","On mixed-version clusters, finish the upgrade so every node supports V2 before migrating"],"exampleFix":"// cassandra.yaml\n// before\npaxos_variant: v1\n// after\npaxos_variant: v2","handlingStrategy":"validation","validationCode":"// before migrating, on each node verify:\nString variant = System.getProperty(\"cassandra.paxos_variant\") /* or check cassandra.yaml */;\nif (!\"v2\".equals(variant)) throw new IllegalStateException(\"Set paxos_variant=v2 before consensus migration\");","typeGuard":null,"tryCatchPattern":"try { migration.start(); } catch (IllegalStateException e) { /* reconfigure paxos_variant=v2, rolling restart, retry */ }","preventionTips":["Set paxos_variant: v2 in cassandra.yaml on all nodes before planning migrations","Complete version upgrades before enabling migration features","Document config prerequisites for migration runbooks"],"tags":["paxos","configuration","consensus-migration","precondition"],"backgroundTag":"invalid-config-value","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"}