TechnitiumSoftware/DnsServer · error · DhcpServerException

Cannot update DNS zone '{zoneInfo.DisplayName}': not a prima

Error message

Cannot update DNS zone '{zoneInfo.DisplayName}': not a primary or a forwarder zone.

What it means

Thrown by DhcpServer when it tries to update DNS records for a DHCP scope but the existing DNS zone matching scope.DomainName has a type other than Primary or Forwarder (e.g. Secondary, Stub, Cache). Only Primary/Forwarder zones can be dynamically written by DHCP, so updating a read-only zone is refused. The guard only fires when the conflicting zone name exactly equals the scope's domain name.

Source

Thrown at DnsServerCore/Dhcp/DhcpServer.cs:803

                    zoneInfo = _dnsServer.AuthZoneManager.CreatePrimaryZone(scope.DomainName);
                    if (zoneInfo is null)
                    {
                        _log.Write("DHCP Server failed to create DNS primary zone '" + scope.DomainName + "'.");
                        return;
                    }

                    //set permissions
                    _authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
                    _authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
                    _authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.DHCP_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
                    _authManager.SaveConfigFile();

                    _log.Write("DHCP Server create DNS primary zone '" + zoneInfo.DisplayName + "'.");
                }
                else if ((zoneInfo.Type != AuthZoneType.Primary) && (zoneInfo.Type != AuthZoneType.Forwarder))
                {
                    if (zoneInfo.Name.Equals(scope.DomainName, StringComparison.OrdinalIgnoreCase))
                        throw new DhcpServerException("Cannot update DNS zone '" + zoneInfo.DisplayName + "': not a primary or a forwarder zone.");

                    //create new primary zone
                    zoneInfo = _dnsServer.AuthZoneManager.CreatePrimaryZone(scope.DomainName);
                    if (zoneInfo is null)
                    {
                        _log.Write("DHCP Server failed to create DNS primary zone '" + scope.DomainName + "'.");
                        return;
                    }

                    //set permissions
                    _authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
                    _authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
                    _authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _authManager.GetGroup(Group.DHCP_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
                    _authManager.SaveConfigFile();

                    _log.Write("DHCP Server create DNS primary zone '" + zoneInfo.DisplayName + "'.");
                }

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. In the DNS UI/API, convert the existing zone matching scope.DomainName to type Primary or Forwarder, then re-enable the scope.
  2. Delete or rename the conflicting Secondary/Stub zone so DHCP can create its own primary zone.
  3. Change the scope's DomainName to a sub-domain for which no non-Primary zone exists.

Example fix

// before: scope.DomainName == 'corp.local' but a Secondary zone 'corp.local' exists
// after: change zone type to Primary (or remove it) before enabling the scope
_dnsServer.AuthZoneManager.SetZoneType('corp.local', AuthZoneType.Primary);
_dhcpServer.EnableScope('corp');
Defensive patterns

Strategy: validation

Validate before calling

var zone = _dnsServer.AuthZoneManager.GetZone(scope.DomainName);
if (zone != null && zone.Type != AuthZoneType.Primary && zone.Type != AuthZoneType.Forwarder)
    throw new InvalidOperationException($"Zone '{scope.DomainName}' is {zone.Type}; convert to Primary/Forwarder before enabling DHCP scope.");

Type guard

static bool ZoneIsWritable(AuthZoneInfo z) => z != null && (z.Type == AuthZoneType.Primary || z.Type == AuthZoneType.Forwarder);

Try / catch

try { _dhcpServer.EnableScope(scope.Name); }
catch (DhcpServerException ex) when (ex.Message.Contains("not a primary or a forwarder zone"))
{ /* convert zone type, then retry once */ }

Prevention

When it happens

Trigger: Activating/enabling a DHCP scope whose DomainName equals an existing AuthZone with zoneInfo.Type not in {Primary, Forwarder}. Concretely the check `(zoneInfo.Type != AuthZoneType.Primary) && (zoneInfo.Type != AuthZoneType.Forwarder)` AND `zoneInfo.Name.Equals(scope.DomainName, OrdinalIgnoreCase)` both hold.

Common situations: Admin manually created a Secondary or Stub zone for the same domain the DHCP scope serves. Zone type changed after scope creation. Split-horizon / conditional-forwarder setups that produced a non-Primary zone with the scope's domain.

Related errors


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