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

  1. Treat as a serious consistency failure: capture logs, then rebuild the cluster (leave+rejoin) to recreate a valid primary zone.
  2. Check filesystem permissions and free space for the zones directory and ensure no external process (AV, sync agent) is deleting zone files.
  3. Upgrade/review the DNS server build — this path indicates the zone-conversion did not yield the expected zone, which may be a defect.
  4. 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

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


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