TechnitiumSoftware/DnsServer · critical · DnsServerException
Failed to promote to Primary node: the Cluster Primary zone
Error message
Failed to promote to Primary node: the Cluster Primary zone does not exist.
What it means
Thrown by PromoteToPrimaryNodeAsync after it has already converted the secondary catalog zone to a catalog zone and promoted the self node: GetAuthZoneInfo(_clusterDomain) returns null where the now-primary cluster zone is expected. Because this fires deep in the promote flow (after irreversible promotion steps), it signals that the zone-type conversion or the secondary-to-primary zone conversion did not produce the expected primary zone — a corrupt or partially-applied state.
Source
Thrown at DnsServerCore/Cluster/ClusterManager.cs:2001
continue;
updatedClusterNodes[existingClusterNode.Key] = existingClusterNode.Value;
}
//update cluster nodes
_clusterNodes = updatedClusterNodes;
//promote self node to primary immediately
selfNewPrimaryNode.PromoteToPrimaryNode();
//convert cluster secondary catalog zone to catalog zone along with all its member zones
if (clusterCatalogZoneInfo.Type == AuthZoneType.SecondaryCatalog)
clusterCatalogZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.ConvertZoneTypeTo(clusterCatalogZoneInfo.Name, AuthZoneType.Catalog);
//get converted primary cluster zone info
clusterZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(_clusterDomain);
if (clusterZoneInfo is null)
throw new DnsServerException("Failed to promote to Primary node: the Cluster Primary zone does not exist.");
//sign cluster zone in case when DNSSEC private keys were not available during ConvertZoneTypeTo() operation
if (clusterZoneInfo.ApexZone.DnssecStatus == AuthZoneDnssecStatus.Unsigned)
{
DnssecPrivateKey kskPrivateKey = DnssecPrivateKey.Create(DnssecAlgorithm.ECDSAP256SHA256, DnssecPrivateKeyType.KeySigningKey);
DnssecPrivateKey zskPrivateKey = DnssecPrivateKey.Create(DnssecAlgorithm.ECDSAP256SHA256, DnssecPrivateKeyType.ZoneSigningKey);
zskPrivateKey.RolloverDays = 90;
_dnsWebService.DnsServer.AuthZoneManager.SignPrimaryZone(clusterZoneInfo.Name, kskPrivateKey, zskPrivateKey, 3600, false);
}
//find existing record TTL values
FindExistingRecordTtlValues(out uint nsTtl, out uint aTtl);
//remove old primary node records from cluster primary zone and save zone file
if (existingPrimaryNode is not null)
RemoveClusterPrimaryZoneRecordsFor(existingPrimaryNode);
View on GitHub (pinned to d0484b6c1e)
Solutions
- Treat as a serious consistency failure: capture logs, then rebuild the cluster (leave+rejoin) to recreate a valid primary zone.
- Check filesystem permissions and free space for the zones directory and ensure no external process (AV, sync agent) is deleting zone files.
- Upgrade/review the DNS server build — this path indicates the zone-conversion did not yield the expected zone, which may be a defect.
- Restore the cluster zone from backup if a known-good copy exists.
Example fix
// before: bare promote that surfaces this mid-flow error
await clusterManager.PromoteToPrimaryNodeAsync(forceDeletePrimary: false);
// after: detect the broken state and rebuild the cluster
try
{
await clusterManager.PromoteToPrimaryNodeAsync(forceDeletePrimary: false);
}
catch (DnsServerException ex) when (ex.Message.Contains("Cluster Primary zone does not exist"))
{
log.Error("Promote left cluster zone missing; rebuilding cluster.", ex);
await clusterManager.LeaveClusterAsync(force: true);
await clusterManager.JoinClusterAsync(primaryUrl, creds, ct);
throw; // surface to operator for manual verify
} Defensive patterns
Strategy: fallback
Validate before calling
// Pre-check before promoting: both cluster zones must exist and be writable
string catalog = "cluster-catalog." + clusterManager.ClusterDomain;
if (dnsServer.AuthZoneManager.GetAuthZoneInfo(catalog) is null
|| dnsServer.AuthZoneManager.GetAuthZoneInfo(clusterManager.ClusterDomain) is null)
throw new InvalidOperationException("Cluster zones missing; rebuild before promoting.");
await clusterManager.PromoteToPrimaryNodeAsync(forceDeletePrimary: false); Type guard
static bool ClusterZonesConsistent(DnsWebService svc, string clusterDomain)
=> svc.DnsServer.AuthZoneManager.GetAuthZoneInfo(clusterDomain) is not null
&& svc.DnsServer.AuthZoneManager.GetAuthZoneInfo("cluster-catalog." + clusterDomain) is not null; Try / catch
try { await clusterManager.PromoteToPrimaryNodeAsync(false); }
catch (DnsServerException ex) when (ex.Message.Contains("Cluster Primary zone does not exist"))
{
// mid-flow consistency failure: rebuild cluster from scratch
log.Error("Promote produced inconsistent zone state; rebuilding cluster.", ex);
await clusterManager.LeaveClusterAsync(force: true);
await clusterManager.JoinClusterAsync(primaryUrl, creds, ct);
throw;
} Prevention
- Verify zone directory permissions and free space before promoting.
- Ensure no AV/sync agent deletes zone files during promotion.
- Keep the DNS server patched; this path indicates a conversion defect worth reporting upstream.
- Back up cluster zones before promotion so a failed convert can be restored.
When it happens
Trigger: Promotion reached the post-conversion re-read of the cluster zone, but GetAuthZoneInfo(_clusterDomain) is null — e.g. ConvertZoneTypeTo/cleanup removed the zone, the zone file failed to persist, or the cluster domain zone was already gone and the earlier check (198) was bypassed by a code change.
Common situations: Disk/permission error writing the converted zone file; antivirus or another process removed the zone file mid-promotion; a bug in ConvertZoneTypeTo that leaves no primary zone; concurrent zone deletion racing with promotion. This is an internal-consistency failure more than a user-config error.
Related errors
- Failed to promote to Primary node: the Cluster Secondary Cat
- Failed to promote to Primary node: the Cluster Secondary zon
- Failed to update Primary node: the Cluster Secondary Catalog
- Failed to promote to Primary node: the Cluster is not initia
- Failed to promote to Primary node: only Secondary nodes can
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/da0fc9909a89cfaf.
Report an issue: GitHub.