{"record":{"id":"e8d21fb87d7af656","repo":"apache/cassandra","slug":"booting-with-clustermetadata-from-file","errorCode":null,"errorMessage":"Booting with ClusterMetadata from file: ","messagePattern":"Booting with ClusterMetadata from file: ","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/tcm/Startup.java","lineNumber":797,"sourceCode":"         * Node is starting for the first time, and should attempt to either discover existing CMS, or\n         * participate in the leader election to establish a new one.\n         */\n        VOTE,\n        /**\n         * Node is starting for the first time, and is a designated first CMS node and can become a first CMS\n         * node upon boot.\n         */\n        FIRST_CMS,\n        /**\n         * Node has to pick Cluster Metadata from the specified file. Used for testing and for (improbable) disaster recovery.\n         */\n        BOOT_WITH_CLUSTERMETADATA;\n\n        static StartupMode get(Set<InetAddressAndPort> seeds)\n        {\n            if (CassandraRelevantProperties.TCM_UNSAFE_BOOT_WITH_CLUSTERMETADATA.isPresent())\n            {\n                logger.warn(\"Booting with ClusterMetadata from file: \" + CassandraRelevantProperties.TCM_UNSAFE_BOOT_WITH_CLUSTERMETADATA.getString());\n                return BOOT_WITH_CLUSTERMETADATA;\n            }\n            if (seeds.isEmpty())\n                throw new IllegalArgumentException(\"Can not initialize CMS without any seeds\");\n            boolean hasAnyEpoch = SystemKeyspaceStorage.hasAnyEpoch();\n\n            // For CCM and local dev clusters\n            boolean isOnlySeed = DatabaseDescriptor.getSeeds().size() == 1\n                                 && DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddressAndPort())\n                                 && DatabaseDescriptor.getSeeds().iterator().next().getAddress().isLoopbackAddress();\n            boolean hasBootedBefore = SystemKeyspace.getLocalHostId() != null;\n            logger.info(\"hasAnyEpoch = {}, hasBootedBefore = {}\", hasAnyEpoch, hasBootedBefore);\n            if (!hasAnyEpoch && hasBootedBefore &&\n                // Atomic long processor currently does not support upgrades\n                !CassandraRelevantProperties.TCM_USE_ATOMIC_LONG_PROCESSOR.getBoolean())\n                return UPGRADE;\n            else if (hasAnyEpoch)\n                return NORMAL;","sourceCodeStart":779,"sourceCodeEnd":815,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/Startup.java#L779-L815","documentation":"StartupMode.get selects how a node boots its cluster metadata. When the TCM_UNSAFE_BOOT_WITH_CLUSTERMETADATA system property is present, it logs a warning that the node will boot with a ClusterMetadata read from the given file and returns BOOT_WITH_CLUSTERMETADATA, bypassing seed-based and epoch-based startup mode resolution.","triggerScenarios":"Any node startup where -Dcassandra.tcm_unsafe_boot_with_clustermetadata=<file> is set on the JVM, regardless of seeds or existing epochs; get() checks that property first.","commonSituations":"Recovering a cluster whose CMS/TCM log was destroyed; staging metadata offline then booting from it; a leftover recovery flag in cassandra-env.sh reaching production.","solutions":["Verify the flag and file path are intentional; the node will trust that file's metadata wholesale.","Sanity-check the file: it must be a serialized ClusterMetadata snapshot consistent with the node's host ID and tokens.","Remove the property once recovery is complete so subsequent restarts use normal startup modes.","Alternatively unset the property and rely on seeds plus SystemKeyspaceStorage.hasAnyEpoch() to pick UPGRADE or NORMAL modes."],"exampleFix":"// before (cassandra-env.sh)\nJVM_OPTS=\"$JVM_OPTS -Dcassandra.tcm_unsafe_boot_with_clustermetadata=/var/lib/cassandra/metadata.bin\"\n// after (recovery finished)\n# property removed; normal startup applies","handlingStrategy":"validation","validationCode":"// Verify the metadata file exists before selecting the mode\nString f = CassandraRelevantProperties.TCM_UNSAFE_BOOT_WITH_CLUSTERMETADATA.getString();\nif (f != null && !new File(f).exists()) {\n    throw new IllegalArgumentException(\"ClusterMetadata file missing: \" + f);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only set the property for documented recovery procedures.","Remove the flag immediately after recovery completes.","Validate file contents against the node's host ID and tokens before boot."],"tags":["tcm","startup","unsafe-flag","bootstrap"],"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-14T16:17:12.679Z"}