TechnitiumSoftware/DnsServer · error · InvalidOperationException

Cannot delete SOA record.

Error message

Cannot delete SOA record.

What it means

Thrown by PrimaryZone.DeleteRecords when the requested type is DnsResourceRecordType.SOA. The SOA record is mandatory and defines zone authority, so deleting the entire RRset is treated as a programming error and surfaced as an InvalidOperationException rather than a data validation failure.

Source

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

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

                        TriggerNotify();

                        return true;
                    }

                    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();

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Exclude DnsResourceRecordType.SOA from the set of types passed to DeleteRecords.
  2. Use SetRecords(SOA, newRecords) to replace the SOA RRset instead of deleting it.
  3. Skip SOA in any 'clear all records' helper.

Example fix

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

// after
foreach (var type in allTypes.Where(t => t != DnsResourceRecordType.SOA))
    zone.DeleteRecords(type);
Defensive patterns

Strategy: type-guard

Validate before calling

var protectedTypes = new[] { DnsResourceRecordType.SOA };
foreach (var type in types.Except(protectedTypes))
    zone.DeleteRecords(type);

Type guard

static bool IsDeletableRrsetType(DnsResourceRecordType t) =>
    t != DnsResourceRecordType.SOA;

Try / catch

null

Prevention

When it happens

Trigger: Calling zone.DeleteRecords(DnsResourceRecordType.SOA) on any PrimaryZone instance. The switch matches the SOA case before the default branch.

Common situations: Generic cleanup loops that iterate all record types and call DeleteRecords for each; bulk-delete tooling that does not exclude SOA/NS; refactoring a record-wipe routine.

Related errors


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