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
- Confirm via GetSelfNode().Type that this node is actually a Secondary before promoting.
- If already Primary, no action is needed; treat as success/idempotent.
- 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
- Make promote idempotent: treat already-primary as success.
- Refresh node type via resync if it shows Unknown before promoting.
- Disable the promote action on non-secondary nodes.
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
- Failed to leave Cluster: only Secondary nodes can leave the
- Failed to leave Cluster: a Primary self node cannot leave th
- Failed to update Primary node: the specified node is the sel
- Failed to refresh configuration: only Secondary nodes can sy
- Failed to resync configuration: only Secondary nodes can syn
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/067d8e972efc45df.
Report an issue: GitHub.