TechnitiumSoftware/DnsServer · error · InvalidOperationException

Cannot update DNSSEC records.

Error message

Cannot update DNSSEC records.

What it means

Thrown by PrimaryZone.UpdateRecord when oldRecord.Type is a DNSSEC type (DNSKEY, RRSIG, NSEC, NSEC3PARAM, NSEC3). DNSSEC records are regenerated by the signing engine, so updating them manually is rejected as InvalidOperationException. Mirrors the protections on Add/Delete.

Source

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

                    }

                    return false;
            }
        }

        public override void UpdateRecord(DnsResourceRecord oldRecord, DnsResourceRecord newRecord)
        {
            switch (oldRecord.Type)
            {
                case DnsResourceRecordType.SOA:
                    throw new InvalidOperationException("Cannot update record: use SetRecords() for " + oldRecord.Type.ToString() + " record");

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

                default:
                    if (oldRecord.Type != newRecord.Type)
                        throw new InvalidOperationException("Old and new record types do not match.");

                    if ((_dnssecStatus != AuthZoneDnssecStatus.Unsigned) && newRecord.GetAuthGenericRecordInfo().Disabled)
                        throw new DnsServerException("Cannot update record: disabling records in a signed zones is not supported.");

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

                    if (!TryDeleteRecord(oldRecord.Type, oldRecord.RDATA, out DnsResourceRecord deletedRecord))
                        throw new DnsServerException("Cannot update record: the record does not exists to be updated.");

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

                    List<DnsResourceRecord> allDeletedRecords = new List<DnsResourceRecord>(deletedRecords.Count + 1);
                    allDeletedRecords.Add(deletedRecord);

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Exclude DNSSEC types from UpdateRecord; trigger re-signing instead.
  2. Branch on type so DNSSEC records are never passed to UpdateRecord.
  3. For key rollover, use the zone's DNSSEC private-key management API rather than record mutation.

Example fix

// before
zone.UpdateRecord(oldRecord, newRecord);

// after
if (IsDnssecType(oldRecord.Type))
    throw new InvalidOperationException("DNSSEC records are managed by signing.");
zone.UpdateRecord(oldRecord, newRecord);
Defensive patterns

Strategy: type-guard

Validate before calling

if (IsDnssecType(oldRecord.Type))
    throw new InvalidOperationException("DNSSEC records are managed by signing.");
zone.UpdateRecord(oldRecord, newRecord);

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.UpdateRecord(oldRecord, newRecord) where oldRecord.Type is a DNSSEC record type.

Common situations: Generic record-editing pipelines that handle all types uniformly; key rollover scripts that try to swap a DNSKEY via UpdateRecord.

Related errors


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