TechnitiumSoftware/DnsServer · error · InvalidOperationException

Old and new record types do not match.

Error message

Old and new record types do not match.

What it means

Thrown by PrimarySubDomainZone.UpdateRecord when oldRecord.Type != newRecord.Type. UpdateRecord is a same-type replace (delete-old/add-new at the same RRset), so a type change is undefined; the guard rejects it with InvalidOperationException before any state mutation.

Source

Thrown at DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs:233

        }

        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 ((_primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned) && newRecord.GetAuthGenericRecordInfo().Disabled)
                        throw new DnsServerException("Cannot update record: disabling records in a signed zones is not supported.");

                    if (newRecord.OriginalTtlValue > _primaryZone.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 InvalidOperationException("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);
                    allDeletedRecords.AddRange(deletedRecords);

                    _primaryZone.CommitAndIncrementSerial(allDeletedRecords, addedRecords);

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Ensure old and new share the same Type before calling UpdateRecord.
  2. For a genuine type change, delete the old record and add the new one as separate operations.
  3. Validate the pairing in the caller so mismatched types never reach the API.

Example fix

// before
zone.UpdateRecord(oldARecord, newAaaaRecord);

// after
if (oldRecord.Type != newRecord.Type)
{
    zone.DeleteRecord(oldRecord.Type, oldRecord.RDATA);
    zone.AddRecord(newRecord);
}
else
    zone.UpdateRecord(oldRecord, newRecord);
Defensive patterns

Strategy: validation

Validate before calling

if (oldRecord.Type != newRecord.Type)
    throw new InvalidOperationException("Record types differ; delete + add instead.");
zone.UpdateRecord(oldRecord, newRecord);

Type guard

static bool SameRecordType(DnsResourceRecord a, DnsResourceRecord b) => a.Type == b.Type;

Prevention

When it happens

Trigger: zone.UpdateRecord(oldRecord, newRecord) where the two records differ in Type (e.g., old is A, new is AAAA).

Common situations: Mis-ordered arguments; 'migrating' a name from one record type to another via Update instead of delete+add; record-import pipelines that recompute type per row.

Related errors


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