TechnitiumSoftware/DnsServer · error · DnsServerException

Failed to update Secondary node: the specified node to updat

Error message

Failed to update Secondary node: the specified node to update must be a Secondary node.

What it means

UpdateSecondaryNode found the node by ID, but its Type is not Secondary (it is the Primary). Only Secondary nodes are valid targets for this update; the Primary's identity is managed separately.

Source

Thrown at DnsServerCore/Cluster/ClusterManager.cs:830

            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.");
            }

            bool secondaryNodeDomainChanged = !secondaryNode.Name.Equals(secondaryNodeUrl.Host, StringComparison.OrdinalIgnoreCase);

            //find existing record TTL values
            FindExistingRecordTtlValues(out uint nsTtl, out uint aTtl);

            //update cluster zone to remove existing records for secondary node
            RemoveClusterPrimaryZoneRecordsFor(secondaryNode);

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Target a node whose Type is Secondary
  2. Refresh cluster state to learn current roles before editing
  3. Re-select the node after any topology change

Example fix

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

// after
var node = clusterNodes.First(n => n.Id == id);
if (node.Type != ClusterNodeType.Secondary)
    throw new InvalidOperationException("Pick a Secondary node to update.");
clusterManager.UpdateSecondaryNode(id, url, ips, cert);
Defensive patterns

Strategy: validation

Validate before calling

var node = clusterState.ClusterNodes.FirstOrDefault(n => n.Id == id);
if (node is null || node.Type != ClusterNodeType.Secondary)
    return BadRequest("Select a Secondary node.");
clusterManager.UpdateSecondaryNode(id, url, ips, cert);

Try / catch

catch (DnsServerException ex) when (ex.Message.Contains("must be a Secondary node"))
{ /* refresh roles and let user re-pick */ }

Prevention

When it happens

Trigger: Passing the Primary node's ID into UpdateSecondaryNode; a node whose role changed from Secondary to Primary after the caller cached it.

Common situations: Promotion or demotion flipping a node's role; a UI reusing a selected node across a role change; treating the self/Primary ID as editable.

Related errors


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