TechnitiumSoftware/DnsServer · error · DnsServerException

Failed to promote to Primary node: only Secondary nodes can

Error message

Failed to promote to Primary node: only Secondary nodes can be promoted to Primary nodes.

What it means

Thrown by PromoteToPrimaryNodeAsync when GetSelfNode().Type != ClusterNodeType.Secondary. Promotion is only defined for Secondary nodes becoming Primary; a node that is already Primary (or Unknown) cannot be 'promoted to primary' again. The check runs after the ClusterInitialized check.

Source

Thrown at DnsServerCore/Cluster/ClusterManager.cs:1945

            {
                _configRetryIntervalSeconds = primaryNodeClusterInfo.ConfigRetryIntervalSeconds;
                saveConfig = true;
            }

            //save changes
            if (saveConfig)
                SaveConfigFile();
        }

        public async Task PromoteToPrimaryNodeAsync(bool forceDeletePrimary)
        {
            if (!ClusterInitialized)
                throw new DnsServerException("Failed to promote to Primary node: the Cluster is not initialized.");

            //do validation
            ClusterNode selfNewPrimaryNode = GetSelfNode();
            if (selfNewPrimaryNode.Type != ClusterNodeType.Secondary)
                throw new DnsServerException("Failed to promote to Primary node: only Secondary nodes can be promoted to Primary nodes.");

            string clusterCatalogDomain = "cluster-catalog." + _clusterDomain;

            AuthZoneInfo clusterCatalogZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(clusterCatalogDomain);
            if (clusterCatalogZoneInfo is null)
                throw new DnsServerException("Failed to promote to Primary node: the Cluster Secondary Catalog zone does not exist.");

            AuthZoneInfo clusterZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(_clusterDomain);
            if (clusterZoneInfo is null)
                throw new DnsServerException("Failed to promote to Primary node: the Cluster Secondary zone does not exist.");

            //stop cluster config refresh timer
            StopConfigRefreshTimer();

            //resync config and delete current primary node from the cluster immediately
            ClusterNode existingPrimaryNode = GetPrimaryNode();

            if (!forceDeletePrimary)

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Confirm via GetSelfNode().Type that this node is actually a Secondary before promoting.
  2. If already Primary, no action is needed; treat as success/idempotent.
  3. Resync config (TriggerResyncForConfig) to correct Unknown type, then retry if appropriate.

Example fix

// before
await clusterManager.PromoteToPrimaryNodeAsync(forceDeletePrimary: false);

// after
var self = clusterManager.GetSelfNode();
if (self.Type == ClusterNodeType.Primary)
    return Ok("Already primary."); // idempotent no-op
if (self.Type != ClusterNodeType.Secondary)
    return BadRequest($"Cannot promote: node type is {self.Type}.");
await clusterManager.PromoteToPrimaryNodeAsync(forceDeletePrimary: false);
Defensive patterns

Strategy: validation

Validate before calling

var self = clusterManager.GetSelfNode();
if (self.Type == ClusterNodeType.Primary)
    return Ok("Already primary.");
if (self.Type != ClusterNodeType.Secondary)
    return BadRequest($"Cannot promote: node type is {self.Type}.");
await clusterManager.PromoteToPrimaryNodeAsync(forceDeletePrimary: false);

Type guard

static bool IsPromotableSecondary(ClusterManager cm)
    => cm.ClusterInitialized && cm.GetSelfNode().Type == ClusterNodeType.Secondary;

Try / catch

try { await clusterManager.PromoteToPrimaryNodeAsync(false); }
catch (DnsServerException ex) when (ex.Message.Contains("only Secondary nodes can be promoted"))
{ /* already primary or unknown; refresh state */ }

Prevention

When it happens

Trigger: Calling PromoteToPrimaryNodeAsync from a node that is already the Primary, or whose type metadata is Unknown/corrupt.

Common situations: Operator double-clicked promote or re-ran it after success; failover already promoted this node but the runbook re-ran; node type set to Unknown by a partial config restore.

Related errors


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