TechnitiumSoftware/DnsServer · error · InvalidOperationException
Cannot delete DNSSEC records.
Error message
Cannot delete DNSSEC records.
What it means
Thrown by PrimarySubDomainZone.DeleteRecords(DnsResourceRecordType type) when 'type' is one of the DNSSEC-managed record types (DNSKEY, RRSIG, NSEC, NSEC3PARAM, NSEC3). DNSSEC records are generated and maintained by the zone-signing machinery, so direct bulk deletion would corrupt the signature chain. The guard raises InvalidOperationException before touching the _entries store.
Source
Thrown at DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs:170
_primaryZone.TriggerNotify();
return true;
}
return false;
}
}
public override bool DeleteRecords(DnsResourceRecordType type)
{
switch (type)
{
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))
{
_primaryZone.CommitAndIncrementSerial(removedRecords);
if (_primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)
_primaryZone.UpdateDnssecRecordsFor(this, type);
_primaryZone.TriggerNotify();
return true;
}
return false;
}
}
View on GitHub (pinned to d0484b6c1e)
Solutions
- Call _primaryZone.UnsignZone() to remove all DNSSEC records through the supported path.
- Filter the type list to exclude DNSSEC types before calling DeleteRecords.
- Do not manage DNSSEC RRs by hand; let the DNSSEC engine add/remove them.
Example fix
// before
zone.DeleteRecords(DnsResourceRecordType.RRSIG);
// after — remove DNSSEC the supported way
if (primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)
primaryZone.UnsignZone(); Defensive patterns
Strategy: validation
Validate before calling
if (IsDnssecRecordType(type)) throw new InvalidOperationException("Cannot delete DNSSEC via DeleteRecords; use UnsignZone.");
zone.DeleteRecords(type); Type guard
static bool IsDnssecRecordType(DnsResourceRecordType t) =>
t == DnsResourceRecordType.DNSKEY || t == DnsResourceRecordType.RRSIG ||
t == DnsResourceRecordType.NSEC || t == DnsResourceRecordType.NSEC3PARAM ||
t == DnsResourceRecordType.NSEC3; Prevention
- Never call DeleteRecords with a DNSSEC type; use UnsignZone for full removal.
- In bulk delete loops, skip DNSSEC types via a shared guard.
- Centralize the IsDnssecRecordType check so every delete path uses it.
When it happens
Trigger: Calling zone.DeleteRecords(DnsResourceRecordType.RRSIG) (or DNSKEY/NSEC/NSEC3PARAM/NSEC3) on a PrimarySubDomainZone.
Common situations: Attempting to 'clean up' DNSSEC records manually after disabling DNSSEC; generic delete-all loops that iterate every record type including DNSSEC types; tooling that treats RRSIG as normal records.
Related errors
- Cannot update DNSSEC records.
- Cannot update record: disabling records in a signed zones is
- Cannot update record: use SetRecords() for {oldRecord.Type}
- Old and new record types do not match.
- Cannot update record: the record does not exists to be updat
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/454a81d64d504663.
Report an issue: GitHub.