TechnitiumSoftware/DnsServer · error · InvalidOperationException

Cannot add DNSSEC record.

Error message

Cannot add DNSSEC record.

What it means

Thrown as InvalidOperationException by PrimaryZone.AddRecord() when the record type is any DNSSEC type (DNSKEY, RRSIG, NSEC, NSEC3PARAM, NSEC3). These are generated exclusively by the signing engine; adding them manually would corrupt the signature/NSEC chain. This is a programming/usage error.

Source

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

                        break;
                }
            }

            switch (record.Type)
            {
                case DnsResourceRecordType.APP:
                    throw new InvalidOperationException("Cannot add record: use SetRecords() for " + record.Type.ToString() + " record");

                case DnsResourceRecordType.DS:
                    throw new InvalidOperationException("Cannot set DS record at zone apex.");

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

                case DnsResourceRecordType.FWD:
                    throw new DnsServerException("The record type is not supported by primary zones.");

                default:
                    if (record.OriginalTtlValue > GetZoneSoaExpire())
                        throw new DnsServerException("Cannot add record: TTL cannot be greater than SOA EXPIRE.");

                    AddRecord(record, out IReadOnlyList<DnsResourceRecord> addedRecords, out IReadOnlyList<DnsResourceRecord> deletedRecords);

                    if (addedRecords.Count > 0)
                    {
                        CommitAndIncrementSerial(deletedRecords, addedRecords);

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

                        TriggerNotify();

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Never AddRecord DNSSEC record types; the signing engine owns them.
  2. Filter DNSKEY/RRSIG/NSEC/NSEC3PARAM/NSEC3 out of the record stream before AddRecord.
  3. To produce DNSSEC records, run the DNSSEC sign/refresh flow on the zone.

Example fix

// before
foreach (var r in imported) zone.AddRecord(r); // throws on DNSSEC types

// after
foreach (var r in imported.Where(r => !IsDnssecType(r.Type)))
    zone.AddRecord(r);
Defensive patterns

Strategy: type-guard

Validate before calling

if (IsDnssecType(record.Type))
    throw new ArgumentException($"{record.Type} is DNSSEC-managed; use signing APIs.");

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

Type guard

static bool IsUserAddable(DnsResourceRecordType t) =>
    t != DnsResourceRecordType.DNSKEY && t != DnsResourceRecordType.RRSIG &&
    t != DnsResourceRecordType.NSEC && t != DnsResourceRecordType.NSEC3PARAM &&
    t != DnsResourceRecordType.NSEC3;

Try / catch

try { zone.AddRecord(record); }
catch (InvalidOperationException ex) when (ex.Message == "Cannot add DNSSEC record.")
{ Log.Error($"{record.Type} is DNSSEC-managed; remove from input."); }

Prevention

When it happens

Trigger: Calling AddRecord with a record whose Type is DNSKEY, RRSIG, NSEC, NSEC3PARAM, or NSEC3 on a primary zone.

Common situations: Importing a signed zone's DNSSEC records via AddRecord; generic record loops that do not exclude DNSSEC types; attempting to hand-patch an RRSIG or NSEC record.

Related errors


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