TechnitiumSoftware/DnsServer · error · DnsServerException

Cannot convert the zone '<currentZoneInfo.DisplayName>'…

Error message

Cannot convert the zone '<currentZoneInfo.DisplayName>' from <currentZoneInfo.TypeName> to <AuthZoneInfo.GetZoneTypeName(newType)> zone: converting the zone will cause lose of DNSSEC private keys.

What it means

Thrown by ConvertZoneTypeTo when converting a Primary zone to a Forwarder zone while the zone carries DNSSEC material (currentZoneInfo.ApexZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned). Converting to Forwarder would discard the zone's authoritative DNSSEC private keys and break chain-of-trust, so the library refuses unless the zone is unsigned.

Solutions

  1. Call UnsignPrimaryZone(zoneName) first to remove DNSSEC material, then retry the conversion.
  2. Keep the zone as Primary if you must retain DNSSEC; do not convert to Forwarder.
  3. Back up DNSSEC private keys before unsigning if you may re-sign later.
  4. Check currentZoneInfo.ApexZone.DnssecStatus and warn the user before attempting the convert.

Example fix

// before
manager.ConvertZoneTypeTo(zoneName, AuthZoneType.Forwarder); // throws if signed

// after
var info = manager.GetAuthZoneInfo(zoneName);
if (info.ApexZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)
    manager.UnsignPrimaryZone(zoneName);
manager.ConvertZoneTypeTo(zoneName, AuthZoneType.Forwarder);
Defensive patterns

Strategy: validation

Validate before calling

var info = manager.GetAuthZoneInfo(zoneName);
if (info.Type == AuthZoneType.Primary && newType == AuthZoneType.Forwarder && info.ApexZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)
    manager.UnsignPrimaryZone(zoneName); // unsign first

Try / catch

catch (DnsServerException ex) when (ex.Message.Contains("DNSSEC private keys")) { manager.UnsignPrimaryZone(zoneName); manager.ConvertZoneTypeTo(zoneName, newType); }

Prevention

When it happens

Trigger: Calling ConvertZoneTypeTo("zone", AuthZoneType.Forwarder) on a signed Primary zone (DnssecStatus is e.g. Signed orInProgress). The Primary->Forwarder branch at line 1449 checks DnssecStatus and throws at line 1451 when it is not Unsigned.

Common situations: Switching a DNSSEC-signed authoritative zone to forwarding without first unsigning it. Promoting then reverting a zone while keys are still loaded. Forgetting that automated DNSSEC signing was enabled on the zone.

Related errors


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

Appendix: source

Thrown at DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs:1451

        public AuthZoneInfo ConvertZoneTypeTo(string zoneName, AuthZoneType newType)
        {
            AuthZoneInfo currentZoneInfo = GetAuthZoneInfo(zoneName);
            if (currentZoneInfo is null)
                throw new DnsServerException("No such zone was found: " + (zoneName.Length == 0 ? "." : zoneName));

            //validate conversion type
            if (currentZoneInfo.Type == newType)
                throw new DnsServerException("Cannot convert the zone '" + currentZoneInfo.DisplayName + "' from " + currentZoneInfo.TypeName + " to " + AuthZoneInfo.GetZoneTypeName(newType) + " zone: the zone is already of the same type.");

            switch (currentZoneInfo.Type)
            {
                case AuthZoneType.Primary:
                    switch (newType)
                    {
                        case AuthZoneType.Forwarder:
                            if (currentZoneInfo.ApexZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)
                                throw new DnsServerException("Cannot convert the zone '" + currentZoneInfo.DisplayName + "' from " + currentZoneInfo.TypeName + " to " + AuthZoneInfo.GetZoneTypeName(newType) + " zone: converting the zone will cause lose of DNSSEC private keys.");

                            break;

                        default:
                            throw new DnsServerException("Cannot convert the zone '" + currentZoneInfo.DisplayName + "' from " + currentZoneInfo.TypeName + " to " + AuthZoneInfo.GetZoneTypeName(newType) + " zone: not supported.");
                    }

                    break;

                case AuthZoneType.Secondary:
                case AuthZoneType.SecondaryForwarder:
                case AuthZoneType.SecondaryCatalog:
                    switch (newType)
                    {
                        case AuthZoneType.Primary:
                        case AuthZoneType.Forwarder:
                        case AuthZoneType.Catalog:
                            break;

View on GitHub (pinned to d0484b6c1e)