TechnitiumSoftware/DnsServer · error · DnsServerException

Failed to ask Secondary node to leave: only a Primary node…

Error message

Failed to ask Secondary node to leave: only a Primary node can ask a Secondary node to leave the Cluster.

What it means

Thrown by AskSecondaryNodeToLeaveClusterAsync when the current server's self node is not the Primary node. Only the Primary can instruct a Secondary to gracefully leave, because the leave handshake involves the Primary updating its node list, zone records, and catalog zone.

Solutions

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

Example fix

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

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

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

Prevention

When it happens

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

Common situations: The leave API request is sent to a Secondary instead of the Primary; wrong server targeted in a multi-node setup.

Related errors


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

Appendix: source

Thrown at DnsServerCore/Cluster/ClusterManager.cs:749

            //save all changes
            SaveConfigFile();

            //notify all secondary nodes
            TriggerNotifyAllSecondaryNodes();

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

            return secondaryNode;
        }

        public async Task<ClusterNode> AskSecondaryNodeToLeaveClusterAsync(int secondaryNodeId)
        {
            if (!ClusterInitialized)
                throw new DnsServerException("Failed to ask Secondary node to leave: the Cluster is not initialized.");

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

            //find existing secondary node
            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.");

View on GitHub (pinned to d0484b6c1e)