TechnitiumSoftware/DnsServer · error · InvalidOperationException

Cannot delete DNSSEC records.

Error message

Cannot delete DNSSEC records.

What it means

Thrown by PrimaryZone.DeleteRecords when the requested type is one of the DNSSEC record types (DNSKEY, RRSIG, NSEC, NSEC3PARAM, NSEC). DNSSEC records are managed internally by the signing engine (UpdateDnssecRecordsFor), so manual deletion is rejected as a programming error.

Source

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

                    }

                    return false;
            }
        }

        public override bool DeleteRecords(DnsResourceRecordType type)
        {
            switch (type)
            {
                case DnsResourceRecordType.SOA:
                    throw new InvalidOperationException("Cannot delete SOA record.");

                case DnsResourceRecordType.DNSKEY:
                case DnsResourceRecordType.RRSIG:
                case DnsResourceRecordType.NSEC:
                case DnsResourceRecordType.NSEC3PARAM:
                case DnsResourceRecordType.NSEC3:
                    throw new InvalidOperationException("Cannot delete DNSSEC records.");

                default:
                    if (_entries.TryRemove(type, out IReadOnlyList<DnsResourceRecord> removedRecords))
                    {
                        CommitAndIncrementSerial(removedRecords);

                        if (_dnssecStatus != AuthZoneDnssecStatus.Unsigned)
                            UpdateDnssecRecordsFor(this, type);

                        TriggerNotify();

                        return true;
                    }

                    return false;
            }
        }

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Filter DNSSEC types (DNSKEY, RRSIG, NSEC, NSEC3PARAM, NSEC3) out before calling DeleteRecords.
  2. To remove DNSSEC data, change the zone's DNSSEC status / re-sign rather than deleting individual RRs.
  3. Maintain an IsDnssecType(type) helper and guard all bulk operations with it.

Example fix

// before
foreach (var type in allTypes)
    zone.DeleteRecords(type);

// after
var dnssec = new[]{ DnsResourceRecordType.DNSKEY, DnsResourceRecordType.RRSIG,
    DnsResourceRecordType.NSEC, DnsResourceRecordType.NSEC3PARAM, DnsResourceRecordType.NSEC3 };
foreach (var type in allTypes.Except(dnssec).Append(SOA-blacklist))
    zone.DeleteRecords(type);
Defensive patterns

Strategy: type-guard

Validate before calling

static readonly HashSet<DnsResourceRecordType> DnssecTypes = new()
{
    DnsResourceRecordType.DNSKEY, DnsResourceRecordType.RRSIG,
    DnsResourceRecordType.NSEC, DnsResourceRecordType.NSEC3PARAM,
    DnsResourceRecordType.NSEC3
};
foreach (var type in types.Where(t => !DnssecTypes.Contains(t) && t != DnsResourceRecordType.SOA))
    zone.DeleteRecords(type);

Type guard

static bool IsDnssecType(DnsResourceRecordType t) =>
    t == DnsResourceRecordType.DNSKEY || t == DnsResourceRecordType.RRSIG ||
    t == DnsResourceRecordType.NSEC || t == DnsResourceRecordType.NSEC3PARAM ||
    t == DnsResourceRecordType.NSEC3;

Try / catch

null

Prevention

When it happens

Trigger: Calling zone.DeleteRecords(type) where type is DNSKEY, RRSIG, NSEC, NSEC3PARAM, or NSEC3 on a PrimaryZone.

Common situations: Generic delete-all loops that sweep every type; tooling that treats DNSSEC records like normal RRs; switching a zone out of signed mode and trying to strip records by hand.

Related errors


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