{"record":{"id":"935adfcebcafa9b5","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-delete-secondary-node-the-specified-nod","errorCode":null,"errorMessage":"Failed to delete Secondary node: the specified node does not exist in the Cluster.","messagePattern":"Failed to delete Secondary node: the specified node does not exist in the Cluster\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":776,"sourceCode":"            //ask secondary node to leave the cluster\n            await secondaryNode.AskSecondaryNodeToLeaveClusterAsync();\n\n            return secondaryNode;\n        }\n\n        public ClusterNode DeleteSecondaryNode(int secondaryNodeId)\n        {\n            if (!ClusterInitialized)\n                throw new DnsServerException(\"Failed to delete Secondary node: the Cluster is not initialized.\");\n\n            if (GetSelfNode().Type != ClusterNodeType.Primary)\n                throw new DnsServerException(\"Failed to delete Secondary node: only a Primary node can delete a Secondary node from the Cluster.\");\n\n            //find existing secondary node\n            IReadOnlyDictionary<int, ClusterNode> existingClusterNodes = _clusterNodes;\n\n            if (!existingClusterNodes.TryGetValue(secondaryNodeId, out ClusterNode secondaryNode))\n                throw new DnsServerException(\"Failed to delete Secondary node: the specified node does not exist in the Cluster.\");\n\n            if (secondaryNode.Type == ClusterNodeType.Primary)\n                throw new DnsServerException(\"Failed to delete Secondary node: the specified node is the Cluster Primary node and cannot be deleted.\");\n\n            //delete secondary node from cluster nodes\n            Dictionary<int, ClusterNode> updatedClusterNodes = new Dictionary<int, ClusterNode>(existingClusterNodes.Count - 1);\n\n            foreach (KeyValuePair<int, ClusterNode> existingClusterNode in existingClusterNodes)\n            {\n                if (existingClusterNode.Key == secondaryNodeId)\n                    continue;\n\n                updatedClusterNodes[existingClusterNode.Key] = existingClusterNode.Value;\n            }\n\n            IReadOnlyDictionary<int, ClusterNode> originalValue = Interlocked.CompareExchange(ref _clusterNodes, updatedClusterNodes, existingClusterNodes);\n            if (!ReferenceEquals(originalValue, existingClusterNodes))\n                throw new InvalidOperationException(\"Failed to delete Secondary node: please try again.\");","sourceCodeStart":758,"sourceCodeEnd":794,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L758-L794","documentation":"Thrown by DeleteSecondaryNode when the provided secondaryNodeId is not found in _clusterNodes. The TryGetValue on existingClusterNodes at line 775 fails, meaning no node with that integer ID currently exists in the cluster.","triggerScenarios":"DeleteSecondaryNode(secondaryNodeId) is called with an ID that does not match any key in the _clusterNodes dictionary. The node may have been already deleted, or the ID is simply wrong.","commonSituations":"Stale UI or client state showing a node that was already removed; double-delete attempt; wrong integer ID passed; race condition where another admin removed the node between the list refresh and the delete call.","solutions":["Refresh the cluster node list and pass a currently-valid secondaryNodeId.","Verify the node exists (_clusterNodes.ContainsKey) before calling.","If the node is already gone, treat it as success (idempotent delete) rather than an error."],"exampleFix":"// before\n_clusterManager.DeleteSecondaryNode(nodeId);\n// after — guard against stale/missing node\nif (!_clusterManager.ClusterNodes.Any(n => n.Key == nodeId))\n    return; // already removed — idempotent no-op\n_clusterManager.DeleteSecondaryNode(nodeId);","handlingStrategy":"validation","validationCode":"// Verify the node exists before deleting — treat missing as idempotent success\nif (!_dnsWebService.ClusterManager.ClusterNodes.Any(n => n.Key == nodeId))\n    return; // already removed\n_dnsWebService.ClusterManager.DeleteSecondaryNode(nodeId);","typeGuard":"static bool NodeExists(ClusterManager cm, int nodeId)\n    => cm.ClusterNodes.Any(n => n.Key == nodeId);","tryCatchPattern":"try\n{\n    _clusterManager.DeleteSecondaryNode(nodeId);\n}\ncatch (DnsServerException ex) when (ex.Message.Contains(\"does not exist in the Cluster\"))\n{\n    // node already deleted — idempotent no-op\n}","preventionTips":["Refresh the node list before issuing delete calls.","Check ClusterNodes for the ID before calling DeleteSecondaryNode.","Handle 'does not exist' as idempotent success in automation scripts."],"tags":["cluster","delete-secondary","not-found","stale-reference"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}