TechnitiumSoftware/DnsServer · error · DnsServerException

Failed to delete Secondary node: only a Primary node can del

Error message

Failed to delete Secondary node: only a Primary node can delete a Secondary node from the Cluster.

What it means

Thrown by DeleteSecondaryNode when the current server's self node is not the Primary node. Only the Primary can remove a Secondary from the authoritative node list, update zone records, and rewrite the catalog zone.

Source

Thrown at DnsServerCore/Cluster/ClusterManager.cs:770

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

            if (secondaryNode.Type == ClusterNodeType.Primary)
                throw new DnsServerException("Failed to ask Secondary node to leave: the specified node is the Cluster Primary node and cannot be removed.");

            //ask secondary node to leave the cluster
            await secondaryNode.AskSecondaryNodeToLeaveClusterAsync();

            return secondaryNode;
        }

        public ClusterNode DeleteSecondaryNode(int secondaryNodeId)
        {
            if (!ClusterInitialized)
                throw new DnsServerException("Failed to delete Secondary node: the Cluster is not initialized.");

            if (GetSelfNode().Type != ClusterNodeType.Primary)
                throw new DnsServerException("Failed to delete Secondary node: only a Primary node can delete a Secondary node from the Cluster.");

            //find existing secondary node
            IReadOnlyDictionary<int, ClusterNode> existingClusterNodes = _clusterNodes;

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

            if (secondaryNode.Type == ClusterNodeType.Primary)
                throw new DnsServerException("Failed to delete Secondary node: the specified node is the Cluster Primary node and cannot be deleted.");

            //delete secondary node from cluster nodes
            Dictionary<int, ClusterNode> updatedClusterNodes = new Dictionary<int, ClusterNode>(existingClusterNodes.Count - 1);

            foreach (KeyValuePair<int, ClusterNode> existingClusterNode in existingClusterNodes)
            {
                if (existingClusterNode.Key == secondaryNodeId)
                    continue;

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Run DeleteSecondaryNode on the cluster Primary node.
  2. Verify GetSelfNode().Type == ClusterNodeType.Primary before calling.

Example fix

// before
_clusterManager.DeleteSecondaryNode(nodeId);
// after
if (_clusterManager.GetSelfNode().Type != ClusterNodeType.Primary)
    throw new InvalidOperationException("Run on the Primary node.");
_clusterManager.DeleteSecondaryNode(nodeId);
Defensive patterns

Strategy: validation

Validate before calling

if (_dnsWebService.ClusterManager.GetSelfNode().Type != ClusterNodeType.Primary)
    throw new InvalidOperationException("DeleteSecondaryNode must run on the Primary node.");
_dnsWebService.ClusterManager.DeleteSecondaryNode(nodeId);

Type guard

static bool IsPrimaryNode(ClusterManager cm)
    => cm.ClusterInitialized && cm.GetSelfNode().Type == ClusterNodeType.Primary;

Try / catch

try
{
    _clusterManager.DeleteSecondaryNode(nodeId);
}
catch (DnsServerException ex) when (ex.Message.Contains("only a Primary node can delete a Secondary"))
{
    throw new InvalidOperationException("Redirect this request to the cluster Primary node.", ex);
}

Prevention

When it happens

Trigger: DeleteSecondaryNode is called from a Secondary node. The guard at line 769 fires after the ClusterInitialized check.

Common situations: The delete-secondary API request targets a Secondary server instead of the Primary; load balancer routing cluster-management calls to the wrong backend.

Related errors


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