TechnitiumSoftware/DnsServer · error · DnsServerException
Failed to update Primary node: the Primary node domain name
Error message
Failed to update Primary node: the Primary node domain name '{primaryNodeUrl.Host}' could not be resolved to an IP address. What it means
Thrown inside UpdatePrimaryNodeAsync's catch block when DnsClient.ResolveIPAsync throws (rather than returning empty) while resolving primaryNodeUrl.Host, with the original exception wrapped as innerException. This indicates the resolver itself failed — timeout, unreachable server, SERVFAIL, transport error — as opposed to a successful resolution that found no records (error 185).
Source
Thrown at DnsServerCore/Cluster/ClusterManager.cs:1527
public async Task<ClusterNode> UpdatePrimaryNodeAsync(Uri primaryNodeUrl, IReadOnlyList<IPAddress> primaryNodeIpAddresses = null, int primaryNodeId = -1, CancellationToken cancellationToken = default)
{
if (!ClusterInitialized)
throw new DnsServerException("Failed to update Primary node: the Cluster is not initialized.");
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($"The domain name '{primaryNodeUrl.Host}' does not have an A/AAAA record configured.");
primaryNodeIpAddresses = ipAddresses;
}
catch (Exception ex)
{
throw new DnsServerException($"Failed to update Primary node: the Primary node domain name '{primaryNodeUrl.Host}' could not be resolved to an IP address.", ex);
}
}
ClusterNode primaryNode;
if (primaryNodeId < 0)
primaryNode = GetPrimaryNode();
else if (!_clusterNodes.TryGetValue(primaryNodeId, out primaryNode))
throw new DnsServerException("Failed to update Primary node: the specified Primary node ID does not exists in the Cluster.");
if (primaryNode.State == ClusterNodeState.Self)
throw new DnsServerException("Failed to update Primary node: the specified node is the self node and cannot be updated this way.");
if (primaryNode.Type == ClusterNodeType.Secondary)
{
//secondary node was promoted to primary node
ClusterNode formerPrimaryNode = GetPrimaryNode();
View on GitHub (pinned to d0484b6c1e)
Solutions
- Inspect the inner exception for the real DNS error (timeout vs refused vs format) and address that layer.
- Pass primaryNodeIpAddresses explicitly to skip resolution.
- Verify the DNS server used by DnsClient.ResolveIPAsync is reachable and serving the primary hostname.
- If intermittent, retry after confirming network reachability (ping/dig against the resolver).
Example fix
// before
try { await clusterManager.UpdatePrimaryNodeAsync(primaryUrl); }
catch (DnsServerException ex) { /* resolution failed */ }
// after: resolve up front with diagnostics, pass IPs through
IReadOnlyList<IPAddress> ips;
try { ips = await DnsClient.ResolveIPAsync(dnsServer, primaryUrl.Host, dnsServer.IPv6Mode, ct); }
catch (Exception ex) { log.Error("DNS resolve failed", ex); throw; }
if (ips is null || ips.Count == 0) throw new InvalidOperationException("No A/AAAA for " + primaryUrl.Host);
await clusterManager.UpdatePrimaryNodeAsync(primaryUrl, ips, cancellationToken: ct); Defensive patterns
Strategy: try-catch
Validate before calling
if (primaryNodeIpAddresses is null)
{
IReadOnlyList<IPAddress> ips;
try { ips = await DnsClient.ResolveIPAsync(dnsServer, primaryUrl.Host, dnsServer.IPv6Mode, ct); }
catch (Exception ex) { throw new InvalidOperationException($"DNS resolve failed for '{primaryUrl.Host}'.", ex); }
if (ips is null || ips.Count == 0) throw new InvalidOperationException("No A/AAAA records.");
primaryNodeIpAddresses = ips;
}
await clusterManager.UpdatePrimaryNodeAsync(primaryUrl, primaryNodeIpAddresses, cancellationToken: ct); Type guard
static bool IsResolvable(string host, out IPAddress[] ips)
{ try { ips = Dns.GetHostAddresses(host); return ips.Length > 0; } catch { ips = Array.Empty<IPAddress>(); return false; } } Try / catch
try { await clusterManager.UpdatePrimaryNodeAsync(primaryUrl, cancellationToken: ct); }
catch (DnsServerException ex) when (ex.InnerException is not null && ex.Message.Contains("could not be resolved"))
{ /* log innerException, fix resolver reachability, or pass IPs explicitly */ } Prevention
- Supply primaryNodeIpAddresses explicitly in automation to bypass DNS.
- Ensure the resolver used by DnsClient is reachable (port 53 not firewalled).
- Inspect the wrapped inner exception to distinguish timeout vs refused vs format errors.
When it happens
Trigger: UpdatePrimaryNodeAsync with null primaryNodeIpAddresses, and the DNS lookup throws: resolver unreachable, query timeout, network down, invalid hostname format, or the internal DNS client misconfigured.
Common situations: Firewall blocking DNS port 53; the configured upstream resolver is down; the primary hostname is malformed; DNS server service itself is restarting so resolution loops fail; IPv6 connectivity broken when only AAAA resolvers are configured.
Related errors
- The domain name '{primaryNodeUrl.Host}' does not have an A/A
- Failed to join Cluster: the domain name '{primaryNodeUrl.Hos
- Failed to join Cluster: the Primary node domain name '{prima
- Failed to update Primary node: the Cluster is not initialize
- Failed to update Primary node: the specified Primary node ID
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/880bddfff605d730.
Report an issue: GitHub.