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 PrimaryZone.UpdateRecord (default case) when oldRecord.Type != newRecord.Type. UpdateRecord only swaps the rdata of a single RR; it cannot change a record's type. This is a precondition check, surfaced as InvalidOperationException.
Source
Thrown at DnsServerCore/Dns/Zones/PrimaryZone.cs:2756
}
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);
allDeletedRecords.AddRange(deletedRecords);
CommitAndIncrementSerial(allDeletedRecords, addedRecords);
View on GitHub (pinned to d0484b6c1e)
Solutions
- Ensure newRecord is constructed with the same Type as oldRecord.
- If the type really must change, do a Delete(oldType) + Add(newType) sequence instead.
- Assert type equality before calling UpdateRecord in generic code.
Example fix
// before
zone.UpdateRecord(oldRecord, newRecord); // newRecord.Type differs
// 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)
{
zone.DeleteRecord(oldRecord.Type, oldRecord.RDATA);
zone.AddRecord(newRecord);
}
else
zone.UpdateRecord(oldRecord, newRecord); Type guard
static bool TypesMatch(DnsResourceRecord a, DnsResourceRecord b) => a.Type == b.Type;
Try / catch
null
Prevention
- Derive newRecord.Type from oldRecord.Type unless a type change is intended.
- Assert type equality in update formatters before submit.
When it happens
Trigger: Calling zone.UpdateRecord(oldRecord, newRecord) where the two records have different DnsResourceRecordType values.
Common situations: Editor code that builds newRecord from a form where the user changed the type field; copy-paste between update calls with mismatched type constants; refactoring rdata objects across types.
Related errors
- Cannot update record: TTL cannot be greater than SOA EXPIRE.
- Cannot update record: the record does not exists to be updat
- Cannot add record: TTL cannot be greater than SOA EXPIRE.
- Cannot update record: use SetRecords() for {type} record
- Cannot update DNSSEC records.
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/f7b46f9dd8aad3e0.
Report an issue: GitHub.