{"record":{"id":"d99441221195adb7","repo":"apache/cassandra","slug":"can-only-initialize-cluster-identifier-during-epoc","errorCode":null,"errorMessage":"Can only initialize cluster identifier during epoch %d, but current epoch is %d","messagePattern":"Can only initialize cluster identifier during epoch (.+?), but current epoch is (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/ClusterMetadata.java","lineNumber":489,"sourceCode":"     * @param addresses The NodeAddresses of the first CMS node.\n     * @param version Version info for the first CMS node.\n     * @param location The rack & DC of the first CMS node.\n     * @return ClusterMetadata instance in the correct state to constitute the base state of the INITIALIZE_CMS\n     *         transformation\n     */\n    public ClusterMetadata forceInitializedState(int clusterIdentifier,\n                                                 NodeAddresses addresses,\n                                                 NodeVersion version,\n                                                 Location location)\n    {\n        if (this.metadataIdentifier != EMPTY_METADATA_IDENTIFIER)\n            throw new IllegalStateException(String.format(\"Can only initialize cluster identifier once, but it was already set to %d\", this.metadataIdentifier));\n\n        if (clusterIdentifier == EMPTY_METADATA_IDENTIFIER)\n            throw new IllegalArgumentException(\"Can not initialize cluster with empty cluster identifier\");\n\n        if (this.epoch.isAfter(Epoch.FIRST))\n            throw new IllegalStateException(String.format(\"Can only initialize cluster identifier during epoch %d, but current epoch is %d\", Epoch.FIRST.getEpoch(), epoch.getEpoch()));\n\n        // Maybe register the first CMS node. If upgrading from gossip, this should be a no-op\n        Directory withRegistered = directory.with(addresses, location, version);\n        NodeId firstNode = withRegistered.peerId(addresses.broadcastAddress);\n        if (firstNode == null)\n            throw new IllegalStateException(\"Failed to find first CMS node in directory\");\n\n        CMSMembership initialCMS = cmsMembership.startJoining(firstNode).finishJoining(firstNode);\n        return new ClusterMetadata(clusterIdentifier,\n                                   epoch,\n                                   partitioner,\n                                   schema,\n                                   withRegistered,\n                                   tokenMap,\n                                   placements,\n                                   accordFastPath,\n                                   lockedRanges,\n                                   inProgressSequences,","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/ClusterMetadata.java#L471-L507","documentation":"ClusterMetadata.forceInitializedState() may only set the cluster identifier while the metadata log is still at the very first epoch (Epoch.FIRST). Once any transformation has been committed, the epoch advances past FIRST and re-initializing the identifier would corrupt cluster identity, so an IllegalStateException is thrown.","triggerScenarios":"Calling forceInitializedState() when this.epoch.isAfter(Epoch.FIRST) — i.e. after the node has already applied metadata transformations and moved past epoch 1. Also thrown earlier if the identifier was already set.","commonSituations":"Bootstrapping a node against a cluster whose metadata log is already initialized (e.g. joining an existing cluster, or a restart racing with another node's initialization), or accidentally invoking forced initialization during a normal startup path.","solutions":["Do not call forceInitializedState() on an already-initialized cluster; use normal cluster join/log replay instead.","Verify with metadata.epoch that the cluster is still at Epoch.FIRST before forcing initialization.","If this is a fresh cluster, ensure no other initialization path (or another node) committed entries first; if needed, start from a clean metadata log.","If the identifier is already set, no action is needed — initialization already succeeded."],"exampleFix":"// before\nif (!metadata.epoch.isAfter(Epoch.FIRST))\n    ClusterMetadata.current().forceInitializedState(...);\n// after\nif (ClusterMetadata.current().epoch.equals(Epoch.FIRST))\n    cms.forceInitializedState(...);\nelse\n    logger.info(\"Cluster already initialized; skipping forced init\");","handlingStrategy":"validation","validationCode":"if (!ClusterMetadata.current().epoch.equals(Epoch.FIRST)) {\n    throw new IllegalStateException(\"Cluster already initialized past epoch 1; do not force init\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    cms.forceInitializedState(...);\n} catch (IllegalStateException e) {\n    logger.info(\"Cluster already initialized: {}\", e.getMessage());\n}","preventionTips":["Check the current epoch equals Epoch.FIRST before forcing initialization","Only invoke forceInitializedState on a brand-new cluster","Treat an already-set identifier as success, not an error"],"tags":["cassandra","tcm","cluster-initialization","illegal-state"],"backgroundTag":"invalid-state-transition","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"}