TechnitiumSoftware/DnsServer · error · DnsServerException

Failed to join Cluster: the zone '{primaryNodeClusterInfo.Cl

Error message

Failed to join Cluster: the zone '{primaryNodeClusterInfo.ClusterDomain}' already exists. Please delete the '{primaryNodeClusterInfo.ClusterDomain}' zone and try again.

What it means

Before joining, the Secondary finds a local zone matching the cluster domain itself ('<clusterDomain>') already exists. The join would manage this zone, so a pre-existing one (prior cluster, manual import) blocks it.

Source

Thrown at DnsServerCore/Cluster/ClusterManager.cs:1379

                throw new TwoFactorAuthRequiredWebServiceException("Failed to join Cluster: two-factor authentication is required by the Primary node user account.", ex);
            }

            try
            {
                //get cluster info
                ClusterInfo primaryNodeClusterInfo = await primaryNodeApiClient.GetClusterStateAsync(cancellationToken: cancellationToken);

                //do validations
                if (!primaryNodeClusterInfo.ClusterInitialized)
                    throw new DnsServerException("Failed to join Cluster: the Primary node does not have a Cluster initialized.");

                string clusterCatalogDomain = "cluster-catalog." + primaryNodeClusterInfo.ClusterDomain;

                if (_dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(clusterCatalogDomain) is not null)
                    throw new DnsServerException($"Failed to join Cluster: the zone '{clusterCatalogDomain}' already exists. Please delete the '{clusterCatalogDomain}' zone and try again.");

                if (_dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(primaryNodeClusterInfo.ClusterDomain) is not null)
                    throw new DnsServerException($"Failed to join Cluster: the zone '{primaryNodeClusterInfo.ClusterDomain}' already exists. Please delete the '{primaryNodeClusterInfo.ClusterDomain}' zone and try again.");

                //create self node
                string serverDomain = _dnsWebService.DnsServer.ServerDomain;
                if (!serverDomain.EndsWith("." + primaryNodeClusterInfo.ClusterDomain, StringComparison.OrdinalIgnoreCase))
                {
                    int x = serverDomain.IndexOf('.');
                    if (x < 0)
                        serverDomain = serverDomain + "." + primaryNodeClusterInfo.ClusterDomain;
                    else
                        serverDomain = string.Concat(serverDomain.AsSpan(0, x), ".", primaryNodeClusterInfo.ClusterDomain);
                }

                Uri secondaryNodeUrl = new Uri($"https://{serverDomain}:{_dnsWebService.WebServiceTlsPort}/");

                ClusterNode selfSecondaryNode = new ClusterNode(this, RandomNumberGenerator.GetInt32(int.MaxValue), secondaryNodeUrl, secondaryNodeIpAddresses, ClusterNodeType.Secondary, ClusterNodeState.Self);

                //join cluster
                primaryNodeClusterInfo = await primaryNodeApiClient.JoinClusterAsync(selfSecondaryNode.Id, secondaryNodeUrl, secondaryNodeIpAddresses, _dnsWebService.WebServiceTlsCertificate, cancellationToken);

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Delete the existing '<clusterDomain>' zone, then retry join
  2. Fully reset previous cluster state to remove stale zones
  3. Confirm no conflicting zone exists before join

Example fix

// before
await clusterManager.InitializeAndJoinClusterAsync(ips, primaryUrl, user, pass);

// after
if (dnsServer.AuthZoneManager.GetAuthZoneInfo(info.ClusterDomain) is not null)
    dnsServer.AuthZoneManager.DeleteZone(info.ClusterDomain);
await clusterManager.InitializeAndJoinClusterAsync(ips, primaryUrl, user, pass);
Defensive patterns

Strategy: validation

Validate before calling

if (dnsServer.AuthZoneManager.GetAuthZoneInfo(info.ClusterDomain) is not null)
    return Conflict($"Zone '{info.ClusterDomain}' exists; delete it before joining.");
await clusterManager.InitializeAndJoinClusterAsync(ips, primaryUrl, user, pass);

Try / catch

catch (DnsServerException ex) when (ex.Message.Contains(info.ClusterDomain) && ex.Message.Contains("already exists"))
{ /* offer to delete the conflicting cluster-domain zone then retry */ }

Prevention

When it happens

Trigger: Re-joining after a partial join; a zone for the cluster domain created manually or via import; a leftover from a previous cluster with the same domain.

Common situations: Restore from backup; aborted join cleanup; an operator pre-created the domain zone.

Related errors


AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13). Data as JSON: /api/errors/de621183a6491403. Report an issue: GitHub.