{"record":{"id":"6ac9e4bf8f92a676","repo":"apache/cassandra","slug":"node-has-host-id-s-in-system-local-but-is-not-pr","errorCode":null,"errorMessage":"Node has host id %s in system.local, but is not present in cluster metadata - not allowing this node to register. If a bootstrap of this node failed and was aborted with `nodetool abortbootstrap` it should also have its data removed before trying to rebootstrap.","messagePattern":"Node has host id (.+?) in system\\.local, but is not present in cluster metadata - not allowing this node to register\\. If a bootstrap of this node failed and was aborted with `nodetool abortbootstrap` it should also have its data removed before trying to rebootstrap\\.","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/transformations/Register.java","lineNumber":180,"sourceCode":"        UUID localHostId = SystemKeyspace.getLocalHostId();\n        Directory directory = ClusterMetadata.current().directory;\n        if (force || localHostId == null)\n        {\n            NodeId nodeId = register(NodeAddresses.current());\n            localHostId = nodeId.toUUID();\n            SystemKeyspace.setLocalHostId(localHostId);\n            logger.info(\"New node ID obtained {}, (Note: This should happen exactly once per node)\", localHostId);\n            return nodeId;\n        }\n        else if (NodeId.isValidNodeId(localHostId) && directory.peerIds().contains(NodeId.fromUUID(localHostId)))\n        {\n            return NodeId.fromUUID(localHostId);\n        }\n        else\n        {\n            NodeId nodeId = directory.peerId(FBUtilities.getBroadcastAddressAndPort());\n            if (nodeId == null)\n                throw new IllegalStateException(\"Node has host id \"+localHostId+\" in system.local, but is not present in cluster metadata - not allowing this node to register. \" +\n                                                \"If a bootstrap of this node failed and was aborted with `nodetool abortbootstrap` it should also have its data removed before trying to rebootstrap.\");\n            NodeVersion dirVersion = directory.version(nodeId);\n\n            // If this is a node in the process of upgrading, update the host id in the system.local table\n            // TODO: when constructing the initial cluster metadata for upgrade, we include a mapping from\n            //      NodeId to the old HostId. We will need to use this lookup to map between the two for\n            //      hint delivery immediately following an upgrade.\n            if (dirVersion == null || !dirVersion.isUpgraded())\n            {\n                if (directory.hostId(nodeId).equals(localHostId))\n                {\n                    SystemKeyspace.setLocalHostId(nodeId.toUUID());\n                    logger.info(\"Updated local HostId from pre-upgrade version {} to the one which was pre-registered \" +\n                                \"during initial cluster metadata conversion {}\", localHostId, nodeId.toUUID());\n                }\n                else\n                {\n                    throw new RuntimeException(\"HostId read from local system table does not match the one recorded \" +","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/transformations/Register.java#L162-L198","documentation":"Thrown during registration when system.local contains a host id but cluster metadata's directory has no NodeId for this node's broadcast address. CMS trusts cluster metadata as the source of truth; a local host id with no corresponding metadata entry is treated as residue from a failed/aborted bootstrap and registration is blocked.","triggerScenarios":"register() finds localHostId in system.local, is not doing replacement, and directory.peerId(broadcastAddress) returns null.","commonSituations":"Re-bootstrapping a node whose previous bootstrap failed and was aborted with `nodetool abortbootstrap` but whose data (including system.local) was left in place; restoring a node from a snapshot into a fresh cluster.","solutions":["Wipe the node's data directories (including system keyspaces) so system.local is regenerated, then rebootstrap","If aborting a failed bootstrap, always follow `nodetool abortbootstrap` with data directory cleanup","If the node should be a member, restore/verify cluster metadata (cms tool) so it contains this node"],"exampleFix":"# before rebootstrap after abortbootstrap\nnodetool abortbootstrap\n# after: also clean data\ncassandra-stale... -> rm -rf /var/lib/cassandra/data/*  # then restart to rebootstrap cleanly","handlingStrategy":"validation","validationCode":"// before re-registering a node with stale data\nUUID localHostId = SystemKeyspace.getLocalHostId();\nif (localHostId != null && ClusterMetadata.current().directory.peerId(broadcastAddress) == null) {\n    // stale system.local: wipe data dirs before rebootstrap\n}","typeGuard":null,"tryCatchPattern":"try { register(); } catch (IllegalStateException e) { if (e.getMessage().startsWith(\"Node has host id\")) { /* clean data dirs and rebootstrap */ } else throw e; }","preventionTips":["Always follow `nodetool abortbootstrap` with data directory cleanup","Never restore another cluster's data snapshot without wiping system.local","Keep cluster metadata and local state in sync when re-imaging nodes"],"tags":["cluster-membership","stale-state","bootstrap"],"backgroundTag":"entity-not-found","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"}