TechnitiumSoftware/DnsServer · error · DnsServerException

Failed to join Cluster: the Primary Node URL must use the do

Error message

Failed to join Cluster: the Primary Node URL must use the domain name of the Primary node and not its IP address.

What it means

InitializeAndJoinClusterAsync requires the Primary node URL to use a hostname, not an IP literal. IPAddress.TryParse(primaryNodeUrl.Host) succeeding means an IP was supplied; the cluster keys members by domain name and needs a resolvable host for certificates and DNS.

Source

Thrown at DnsServerCore/Cluster/ClusterManager.cs:1334

            {
                _notifyAllSecondaryNodesTimerTriggered = false;
            }
        }

        #endregion

        #region secondary node

        public async Task InitializeAndJoinClusterAsync(IReadOnlyList<IPAddress> secondaryNodeIpAddresses, Uri primaryNodeUrl, string primaryNodeUsername, string primaryNodePassword, string primaryNodeTotp = null, IReadOnlyList<IPAddress> primaryNodeIpAddresses = null, bool ignoreCertificateErrors = false, CancellationToken cancellationToken = default)
        {
            if (ClusterInitialized)
                throw new DnsServerException("Failed to join Cluster: the Cluster is already initialized.");

            if (!_dnsWebService.IsWebServiceTlsEnabled)
                throw new InvalidOperationException();

            if (IPAddress.TryParse(primaryNodeUrl.Host, out _))
                throw new DnsServerException("Failed to join Cluster: the Primary Node URL must use the domain name of the Primary node and not its IP address.");

            if (primaryNodeIpAddresses is null)
            {
                try
                {
                    IReadOnlyList<IPAddress> ipAddresses = await DnsClient.ResolveIPAsync(_dnsWebService.DnsServer, primaryNodeUrl.Host, _dnsWebService.DnsServer.IPv6Mode, cancellationToken);
                    if (ipAddresses.Count < 1)
                        throw new DnsServerException($"Failed to join Cluster: the domain name '{primaryNodeUrl.Host}' does not have an A/AAAA record configured.");

                    primaryNodeIpAddresses = ipAddresses;
                }
                catch (Exception ex)
                {
                    throw new DnsServerException($"Failed to join Cluster: the Primary node domain name '{primaryNodeUrl.Host}' could not be resolved to an IP address. Please specify the Primary node IP address manually.", ex);
                }
            }

            //login to primary node API

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Use the Primary's domain name in the URL (e.g. https://dns-primary.example.com:5380)
  2. Configure a DNS A/AAAA record for the Primary if none exists
  3. If only an IP is available, set up a hostname (hosts/DNS) first

Example fix

// before
var primaryUrl = new Uri("https://10.0.0.5:5380");
await clusterManager.InitializeAndJoinClusterAsync(ips, primaryUrl, user, pass);

// after
var primaryUrl = new Uri("https://dns-primary.example.com:5380");
await clusterManager.InitializeAndJoinClusterAsync(
    ips, primaryUrl, user, pass,
    primaryNodeIpAddresses: new[] { IPAddress.Parse("10.0.0.5") });
Defensive patterns

Strategy: validation

Validate before calling

if (IPAddress.TryParse(primaryNodeUrl.Host, out _))
    return BadRequest("Primary URL must use a domain name, not an IP.");
await clusterManager.InitializeAndJoinClusterAsync(ips, primaryUrl, user, pass);

Try / catch

catch (DnsServerException ex) when (ex.Message.Contains("must use the domain name"))
{ /* prompt for a hostname-based URL */ }

Prevention

When it happens

Trigger: Passing primaryNodeUrl = new Uri("https://10.0.0.5:5380") instead of a hostname; supplying the Primary's IP in the URL while providing IPs separately.

Common situations: Quick lab setups using IPs; copy-paste from a connection string; no DNS name configured for the Primary.

Related errors


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