{"record":{"id":"9c3581f111ca9550","repo":"apache/cassandra","slug":"cluster-is-not-running-unsafe-tcm-mode-can-t-reve","errorCode":null,"errorMessage":"Cluster is not running unsafe TCM mode, can't revert epoch","messagePattern":"Cluster is not running unsafe TCM mode, can't revert epoch","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/CMSOperations.java","lineNumber":268,"sourceCode":"        info.put(COMMITS_PAUSED, Boolean.toString(cms.commitsPaused()));\n        info.put(REPLICATION_FACTOR, metadata.epoch.isBefore(Epoch.FIRST) ? \"\" : ReplicationParams.meta(metadata).toString());\n        info.put(CMS_ID, Integer.toString(metadata.metadataIdentifier));\n        return info;\n    }\n\n    @Override\n    public void snapshotClusterMetadata()\n    {\n        logger.info(\"Triggering cluster metadata snapshot\");\n        Epoch epoch = cms.triggerSnapshot().epoch;\n        logger.info(\"Cluster metadata snapshot triggered at {}\", epoch);\n    }\n\n    @Override\n    public void unsafeRevertClusterMetadata(long epoch)\n    {\n        if (!DatabaseDescriptor.getUnsafeTCMMode())\n            throw new IllegalStateException(\"Cluster is not running unsafe TCM mode, can't revert epoch\");\n        cms.revertToEpoch(Epoch.create(epoch));\n    }\n\n    @Override\n    public String dumpClusterMetadata(long epoch, long transformToEpoch, String version) throws IOException\n    {\n        return cms.dumpClusterMetadata(Epoch.create(epoch), Epoch.create(transformToEpoch), Version.valueOf(version));\n    }\n\n    @Override\n    public String dumpClusterMetadata() throws IOException\n    {\n        return dumpClusterMetadata(Epoch.EMPTY.getEpoch(),\n                                   ClusterMetadata.current().epoch.getEpoch() + 1000,\n                                   NodeVersion.CURRENT.serializationVersion().toString());\n    }\n\n    @Override","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/CMSOperations.java#L250-L286","documentation":"Thrown by CMSOperations.unsafeRevertClusterMetadata when reverting cluster metadata to an earlier epoch is requested while the unsafe TCM mode flag is disabled. Unsafe mode is an explicit opt-in that permits destructive metadata rollback operations.","triggerScenarios":"Calling unsafeRevertClusterMetadata(long epoch) (e.g. via nodetool) when DatabaseDescriptor.getUnsafeTCMMode() returns false.","commonSituations":"Operator tries to roll back metadata after a failed upgrade without having enabled unsafe_tcm_mode in cassandra.yaml, or forgets to restart the node after setting it.","solutions":["Set unsafe_tcm_mode: true in cassandra.yaml and restart the node, then retry the revert.","Confirm with the Cassandra documentation that metadata rollback is required before enabling the flag.","After the revert completes, disable unsafe_tcm_mode again."],"exampleFix":"// before (cassandra.yaml)\n# unsafe_tcm_mode not set\n// after\nunsafe_tcm_mode: true","handlingStrategy":"validation","validationCode":"if (!DatabaseDescriptor.getUnsafeTCMMode()) throw new IllegalStateException(\"Enable unsafe_tcm_mode and restart before reverting epochs\");","typeGuard":null,"tryCatchPattern":"try { ops.unsafeRevertClusterMetadata(epoch); } catch (IllegalStateException e) { logger.error(\"Revert rejected: {}\", e.getMessage()); }","preventionTips":["Enable unsafe_tcm_mode in cassandra.yaml before rollback operations","Remember a node restart is needed for config changes","Disable unsafe mode again after recovery"],"tags":["tcm","config","unsafe-mode"],"backgroundTag":"feature-not-enabled","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"}