{"record":{"id":"69b64cff588e028d","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-add-secondary-node-a-node-with-the-same","errorCode":null,"errorMessage":"Failed to add Secondary node: A node with the same DNS Server Domain Name already exists in the Cluster. Please try again after changing the Secondary node's DNS Server Domain Name.","messagePattern":"Failed to add Secondary node: A node with the same DNS Server Domain Name already exists in the Cluster\\. Please try again after changing the Secondary node's DNS Server Domain Name\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":702,"sourceCode":"        {\n            if (!ClusterInitialized)\n                throw new DnsServerException(\"Failed to add Secondary node: the Cluster is not initialized.\");\n\n            if (GetSelfNode().Type != ClusterNodeType.Primary)\n                throw new DnsServerException(\"Failed to add Secondary node: only a Primary node can add a Secondary node to the Cluster.\");\n\n            string secondaryNodeDomain = secondaryNodeUrl.Host.ToLowerInvariant();\n\n            if (!secondaryNodeDomain.EndsWith(\".\" + _clusterDomain, StringComparison.OrdinalIgnoreCase))\n                throw new DnsServerException(\"Failed to add Secondary node: the Secondary node domain name must be a subdomain of the Cluster domain name.\");\n\n            IReadOnlyDictionary<int, ClusterNode> existingClusterNodes = _clusterNodes;\n\n            //validate for duplicate names\n            foreach (KeyValuePair<int, ClusterNode> existingClusterNode in existingClusterNodes)\n            {\n                if (existingClusterNode.Value.Name.Equals(secondaryNodeUrl.Host, StringComparison.OrdinalIgnoreCase))\n                    throw new DnsServerException(\"Failed to add Secondary node: A node with the same DNS Server Domain Name already exists in the Cluster. Please try again after changing the Secondary node's DNS Server Domain Name.\");\n            }\n\n            //add secondary node to cluster nodes\n            ClusterNode secondaryNode = new ClusterNode(this, secondaryNodeId, secondaryNodeUrl, secondaryNodeIpAddresses, ClusterNodeType.Secondary, ClusterNodeState.Unknown);\n            Dictionary<int, ClusterNode> updatedClusterNodes = new Dictionary<int, ClusterNode>(existingClusterNodes.Count + 1);\n\n            foreach (KeyValuePair<int, ClusterNode> existingClusterNode in existingClusterNodes)\n                updatedClusterNodes[existingClusterNode.Value.Id] = existingClusterNode.Value;\n\n            if (!updatedClusterNodes.TryAdd(secondaryNode.Id, secondaryNode))\n                throw new DnsServerException(\"Failed to add Secondary node: node ID already exists in the Cluster. Please try again.\");\n\n            if (updatedClusterNodes.Count > 255)\n                throw new DnsServerException(\"Failed to add Secondary node: a maximum of 255 nodes are supported by the Cluster.\");\n\n            IReadOnlyDictionary<int, ClusterNode> originalValue = Interlocked.CompareExchange(ref _clusterNodes, updatedClusterNodes, existingClusterNodes);\n            if (!ReferenceEquals(originalValue, existingClusterNodes))\n                throw new DnsServerException(\"Failed to add Secondary node: please try again.\");","sourceCodeStart":684,"sourceCodeEnd":720,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L684-L720","documentation":"Thrown by JoinCluster when an existing cluster node already has the same DNS Server Domain Name (host) as the new Secondary being added. Node names must be unique so NS and address records do not collide in the cluster primary zone.","triggerScenarios":"JoinCluster iterates existingClusterNodes and finds existingClusterNode.Value.Name.Equals(secondaryNodeUrl.Host, OrdinalIgnoreCase) is true for some existing node. This happens when the Secondary's hostname matches a node already in _clusterNodes.","commonSituations":"Re-adding a Secondary node that was asked to leave but not yet deleted from the node list; two Secondary servers configured with the same DNS Server Domain Name; retrying a join after a partial failure that already registered the name.","solutions":["Delete the existing node with the duplicate name first using DeleteSecondaryNode, then retry the join.","Change the new Secondary's DNS Server Domain Name to something unique before joining."],"exampleFix":"// before\n_clusterManager.JoinCluster(nodeId, new Uri(\"https://ns2.cluster.example.com:5380/\"), ips, cert);\n// after — remove the stale duplicate first\nif (_clusterManager.TryGetClusterNode(\"ns2.cluster.example.com\", out var existing))\n    _clusterManager.DeleteSecondaryNode(existing.Id);\n_clusterManager.JoinCluster(nodeId, new Uri(\"https://ns2.cluster.example.com:5380/\"), ips, cert);","handlingStrategy":"validation","validationCode":"// Check for an existing node with the same hostname before joining\nif (_dnsWebService.ClusterManager.TryGetClusterNode(secondaryNodeUrl.Host, out var existing))\n    throw new InvalidOperationException($\"Node '{existing.Name}' already exists; delete it or change the Secondary's domain name.\");\n_dnsWebService.ClusterManager.JoinCluster(nodeId, secondaryNodeUrl, nodeIps, cert);","typeGuard":"static bool IsSecondaryNameUnique(ClusterManager cm, Uri secondaryUrl)\n    => !cm.TryGetClusterNode(secondaryUrl.Host, out _);","tryCatchPattern":"try\n{\n    _dnsWebService.ClusterManager.JoinCluster(nodeId, nodeUrl, nodeIps, cert);\n}\ncatch (DnsServerException ex) when (ex.Message.Contains(\"same DNS Server Domain Name already exists\"))\n{\n    // delete the stale node first, or change the Secondary's domain name, then retry\n    throw;\n}","preventionTips":["Check TryGetClusterNode for the Secondary's hostname before joining.","Delete stale or offline nodes before re-adding a Secondary with the same name.","Ensure each Secondary has a unique DNS Server Domain Name."],"tags":["cluster","join","duplicate","naming","uniqueness"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}