TechnitiumSoftware/DnsServer · error · DnsServerException

Failed to update Secondary node: only a Primary node can upd

Error message

Failed to update Secondary node: only a Primary node can update a Secondary node's details in the Cluster.

What it means

UpdateSecondaryNode is only permitted on the node acting as cluster Primary (GetSelfNode().Type == Primary). Calling it from a Secondary or standalone node is rejected because Secondary nodes cannot edit cluster topology.

Source

Thrown at DnsServerCore/Cluster/ClusterManager.cs:822

            //save all changes
            SaveConfigFile();

            //notify all secondary nodes
            TriggerNotifyAllSecondaryNodes();

            //trigger NS and SOA update for member zones
            TriggerRecordUpdateForClusterCatalogMemberZones();

            return secondaryNode;
        }

        public ClusterNode UpdateSecondaryNode(int secondaryNodeId, Uri secondaryNodeUrl, IReadOnlyList<IPAddress> secondaryNodeIpAddresses, X509Certificate2 secondaryNodeCertificate)
        {
            if (!ClusterInitialized)
                throw new DnsServerException("Failed to update Secondary node: the Cluster is not initialized.");

            if (GetSelfNode().Type != ClusterNodeType.Primary)
                throw new DnsServerException("Failed to update Secondary node: only a Primary node can update a Secondary node's details in the Cluster.");

            IReadOnlyDictionary<int, ClusterNode> clusterNodes = _clusterNodes;

            if (!clusterNodes.TryGetValue(secondaryNodeId, out ClusterNode secondaryNode))
                throw new DnsServerException("Failed to update Secondary node: the specified node does not exist in the Cluster.");

            if (secondaryNode.Type != ClusterNodeType.Secondary)
                throw new DnsServerException("Failed to update Secondary node: the specified node to update must be a Secondary node.");

            //validate for duplicate names
            foreach (KeyValuePair<int, ClusterNode> clusterNode in clusterNodes)
            {
                if (clusterNode.Key == secondaryNodeId)
                    continue; //skip self

                if (clusterNode.Value.Name.Equals(secondaryNodeUrl.Host, StringComparison.OrdinalIgnoreCase))
                    throw new DnsServerException("Failed to update 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.");
            }

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Target the current Primary node - discover it via cluster state and call its API
  2. Refresh the client's notion of which node is Primary before issuing topology edits
  3. Re-run the call against the correct endpoint

Example fix

// before
clusterManager.UpdateSecondaryNode(id, url, ips, cert);

// after
if (clusterManager.GetSelfNode().Type != ClusterNodeType.Primary)
    throw new InvalidOperationException("This node is not the Primary; redirect to the Primary.");
clusterManager.UpdateSecondaryNode(id, url, ips, cert);
Defensive patterns

Strategy: validation

Validate before calling

if (clusterManager.GetSelfNode().Type != ClusterNodeType.Primary)
    return RedirectOrReject("Only the Primary node can update Secondary nodes.");
clusterManager.UpdateSecondaryNode(id, url, ips, cert);

Try / catch

catch (DnsServerException ex) when (ex.Message.Contains("only a Primary node can update"))
{ /* rediscover Primary and retry there */ }

Prevention

When it happens

Trigger: Running the update against a Secondary node's API; an L4 load balancer routing the request to the wrong cluster member; the server was demoted from Primary to Secondary after the client cached its role.

Common situations: Failover or demotion changing which node is Primary mid-session; client targeting a node by IP rather than by role; split-brain where the client talks to a Secondary.

Related errors


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