{"record":{"id":"39c66535d7c7e899","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-ask-secondary-node-to-leave-the-cluster","errorCode":null,"errorMessage":"Failed to ask Secondary node to leave: the Cluster is not initialized.","messagePattern":"Failed to ask Secondary node to leave: the Cluster is not initialized\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":746,"sourceCode":"            //update cluster catalog zone ACLs and save zone file\n            UpdateClusterCatalogZoneOptions();\n\n            //save all changes\n            SaveConfigFile();\n\n            //notify all secondary nodes\n            TriggerNotifyAllSecondaryNodes();\n\n            //trigger NS and SOA update for member zones\n            TriggerRecordUpdateForClusterCatalogMemberZones();\n\n            return secondaryNode;\n        }\n\n        public async Task<ClusterNode> AskSecondaryNodeToLeaveClusterAsync(int secondaryNodeId)\n        {\n            if (!ClusterInitialized)\n                throw new DnsServerException(\"Failed to ask Secondary node to leave: the Cluster is not initialized.\");\n\n            if (GetSelfNode().Type != ClusterNodeType.Primary)\n                throw new DnsServerException(\"Failed to ask Secondary node to leave: only a Primary node can ask a Secondary node to leave the Cluster.\");\n\n            //find existing secondary node\n            if (!_clusterNodes.TryGetValue(secondaryNodeId, out ClusterNode secondaryNode))\n                throw new DnsServerException(\"Failed to ask Secondary node to leave: the specified node does not exist in the Cluster.\");\n\n            if (secondaryNode.Type == ClusterNodeType.Primary)\n                throw new DnsServerException(\"Failed to ask Secondary node to leave: the specified node is the Cluster Primary node and cannot be removed.\");\n\n            //ask secondary node to leave the cluster\n            await secondaryNode.AskSecondaryNodeToLeaveClusterAsync();\n\n            return secondaryNode;\n        }\n\n        public ClusterNode DeleteSecondaryNode(int secondaryNodeId)","sourceCodeStart":728,"sourceCodeEnd":764,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L728-L764","documentation":"Thrown by AskSecondaryNodeToLeaveClusterAsync when ClusterInitialized is false. Asking a node to leave requires an active cluster with a node list to look up the target Secondary.","triggerScenarios":"AskSecondaryNodeToLeaveClusterAsync(secondaryNodeId) is called on a server where _clusterNodes is null or empty. The guard at line 745 fires before the node lookup.","commonSituations":"Calling the leave operation on a non-clustered server; after the cluster was already deleted; on a Secondary that never joined successfully.","solutions":["Check ClusterManager.ClusterInitialized before calling AskSecondaryNodeToLeaveClusterAsync.","Ensure the operation targets the initialized Primary node."],"exampleFix":"// before\nawait _clusterManager.AskSecondaryNodeToLeaveClusterAsync(nodeId);\n// after\nif (!_clusterManager.ClusterInitialized)\n    throw new InvalidOperationException(\"Cluster is not initialized.\");\nawait _clusterManager.AskSecondaryNodeToLeaveClusterAsync(nodeId);","handlingStrategy":"validation","validationCode":"if (!_dnsWebService.ClusterManager.ClusterInitialized)\n    throw new InvalidOperationException(\"Cluster is not initialized; cannot ask a node to leave.\");\nawait _dnsWebService.ClusterManager.AskSecondaryNodeToLeaveClusterAsync(nodeId);","typeGuard":"static bool CanManageClusterNodes(ClusterManager cm) => cm.ClusterInitialized;","tryCatchPattern":"try\n{\n    await _clusterManager.AskSecondaryNodeToLeaveClusterAsync(nodeId);\n}\ncatch (DnsServerException ex) when (ex.Message.Contains(\"ask Secondary node to leave\") && ex.Message.Contains(\"not initialized\"))\n{\n    // no cluster — nothing to leave\n}","preventionTips":["Check ClusterInitialized before calling any node-management method.","Hide or disable leave/delete controls when no cluster is active.","Verify the server is the initialized Primary before issuing node operations."],"tags":["cluster","leave","validation","not-initialized"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}