TechnitiumSoftware/DnsServer · error · DnsServerException

Cannot convert to NSEC3: the zone must be signed with NSEC f

Error message

Cannot convert to NSEC3: the zone must be signed with NSEC for conversion.

What it means

Thrown by PrimaryZone.ConvertToNSec3 when the zone's DNSSEC status is not SignedWithNSEC. The library only permits converting a zone that is currently signed with plain NSEC into the NSEC3 variant; going straight from Unsigned to NSEC3 (or re-converting a zone already on NSEC3) is rejected so the existing NSEC chain can be cleanly disabled first.

Source

Thrown at DnsServerCore/Dns/Zones/PrimaryZone.cs:726

                foreach (AuthZone zone in zones)
                {
                    if (!zone.IsEmpty)
                        nonEmptyZones.Add(zone);
                }

                EnableNSec(nonEmptyZones);

                _dnssecStatus = AuthZoneDnssecStatus.SignedWithNSEC;
            }

            TriggerNotify();
        }

        public void ConvertToNSec3(ushort iterations, byte saltLength)
        {
            if (_dnssecStatus != AuthZoneDnssecStatus.SignedWithNSEC)
                throw new DnsServerException("Cannot convert to NSEC3: the zone must be signed with NSEC for conversion.");

            if (iterations > 50)
                throw new ArgumentOutOfRangeException(nameof(iterations), "NSEC3 iterations valid range is 0-50");

            if (saltLength > 32)
                throw new ArgumentOutOfRangeException(nameof(saltLength), "NSEC3 salt length valid range is 0-32");

            lock (_dnssecUpdateLock)
            {
                IReadOnlyList<AuthZone> zones = _dnsServer.AuthZoneManager.GetApexZoneWithSubDomainZones(_name);

                DisableNSec(zones);
                EnableNSec3(zones, iterations, saltLength);

                _dnssecStatus = AuthZoneDnssecStatus.SignedWithNSEC3;
            }

            TriggerNotify();

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. If the zone is Unsigned, sign it first with NSEC (call SignZone with useNSec3=false), then call ConvertToNSec3.
  2. If the zone is already SignedWithNSEC3 and you want to change salt/iterations, call UpdateNSec3Parameters instead of ConvertToNSec3.
  3. Guard the call with a check on the zone's DnssecStatus property before invoking ConvertToNSec3.

Example fix

// before
zone.ConvertToNSec3(iterations: 2, saltLength: 8);

// after
if (zone.DnssecStatus == AuthZoneDnssecStatus.Unsigned)
    zone.SignZone(keys, dnsKeyTtl, useNSec3: false);
if (zone.DnssecStatus == AuthZoneDnssecStatus.SignedWithNSEC)
    zone.ConvertToNSec3(iterations: 2, saltLength: 8);
else if (zone.DnssecStatus == AuthZoneDnssecStatus.SignedWithNSEC3)
    zone.UpdateNSec3Parameters(iterations: 2, saltLength: 8);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the zone is on NSEC before converting to NSEC3
if (zone.DnssecStatus != AuthZoneDnssecStatus.SignedWithNSEC)
{
    if (zone.DnssecStatus == AuthZoneDnssecStatus.Unsigned)
        zone.SignZone(keys, dnsKeyTtl, useNSec3: false);
    else if (zone.DnssecStatus == AuthZoneDnssecStatus.SignedWithNSEC3)
    {
        zone.UpdateNSec3Parameters(iterations, saltLength);
        return;
    }
}
zone.ConvertToNSec3(iterations, saltLength);

Type guard

static bool CanConvertToNSec3(ApexZone zone) =>
    zone.DnssecStatus == AuthZoneDnssecStatus.SignedWithNSEC;

Try / catch

try
{
    zone.ConvertToNSec3(iterations, saltLength);
}
catch (DnsServerException ex) when (ex.Message.Contains("must be signed with NSEC for conversion"))
{
    // sign with NSEC first, then retry; or route to UpdateNSec3Parameters
}

Prevention

When it happens

Trigger: Calling ConvertToNSec3(iterations, saltLength) on a zone whose DnssecStatus is Unsigned, or calling it again on a zone whose DnssecStatus is already SignedWithNSEC3.

Common situations: A developer enables DNSSEC signing and assumes NSEC3 is the default, calling ConvertToNSec3 without first calling SignZone with useNSec3=false. Or scripting a 're-sign as NSEC3' routine that fires against an already-NSEC3 zone after a reload.

Related errors


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