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
AuthZone.UpdateRecord requires the old and new records to be of the same type. If oldRecord.Type != newRecord.Type, it throws InvalidOperationException. This is because UpdateRecord performs an in-place replacement: it deletes the old record's rdata and adds the new rdata under the same type key. Changing the type would require different validation logic (CNAME exclusivity, singleton rules) that belongs in SetRecords or AddRecord/DeleteRecord sequences.
Source
Thrown at DnsServerCore/Dns/Zones/AuthZone.cs:858
}
public virtual bool DeleteRecords(DnsResourceRecordType type)
{
return _entries.TryRemove(type, out _);
}
public virtual bool DeleteRecord(DnsResourceRecordType type, DnsResourceRecordData rdata)
{
return TryDeleteRecord(type, rdata, out _);
}
public virtual void UpdateRecord(DnsResourceRecord oldRecord, DnsResourceRecord newRecord)
{
if (oldRecord.Type == DnsResourceRecordType.SOA)
throw new InvalidOperationException("Cannot update record: use SetRecords() for " + oldRecord.Type.ToString() + " record");
if (oldRecord.Type != newRecord.Type)
throw new InvalidOperationException("Old and new record types do not match.");
if (!DeleteRecord(oldRecord.Type, oldRecord.RDATA))
throw new DnsWebServiceException("Cannot update record: the old record does not exists.");
AddRecord(newRecord);
}
public virtual IReadOnlyList<DnsResourceRecord> QueryRecords(DnsResourceRecordType type, bool dnssecOk)
{
switch (type)
{
case DnsResourceRecordType.APP:
case DnsResourceRecordType.FWD:
case DnsResourceRecordType.NSEC:
case DnsResourceRecordType.NSEC3:
{
//return only exact type if exists
if (_entries.TryGetValue(type, out IReadOnlyList<DnsResourceRecord> existingRecords))View on GitHub (pinned to d0484b6c1e)
Solutions
- If you need to change the record type, perform a DeleteRecord(oldType, oldRdata) followed by AddRecord(newRecord) instead of UpdateRecord.
- Add a pre-call check: if oldRecord.Type != newRecord.Type, route to delete+add logic.
- In UI/API code, disable the type field when editing an existing record, or validate before submission.
Example fix
// before zone.UpdateRecord(oldARecord, newAaaaRecord); // type mismatch // after zone.DeleteRecord(oldARecord.Type, oldARecord.RDATA); zone.AddRecord(newAaaaRecord);
Defensive patterns
Strategy: validation
Validate before calling
if (oldRecord.Type != newRecord.Type)
throw new ArgumentException($"Record type change not supported by UpdateRecord (old: {oldRecord.Type}, new: {newRecord.Type}). Use DeleteRecord + AddRecord instead.");
zone.UpdateRecord(oldRecord, newRecord); Type guard
static bool TypesMatch(DnsResourceRecord oldRecord, DnsResourceRecord newRecord)
=> oldRecord.Type == newRecord.Type; Prevention
- Validate oldRecord.Type == newRecord.Type before calling UpdateRecord.
- In UI code, disable record type editing or convert type changes to delete+add.
- Add input validation in API handlers for record update requests.
When it happens
Trigger: Calling UpdateRecord where the oldRecord and newRecord have different DnsResourceRecordType values (e.g., oldRecord is type A and newRecord is type AAAA). Common in UI code that allows changing record type in an edit form.
Common situations: Record-edit UIs that let the user change the record type dropdown when editing; migration scripts that 'update' records by changing their type; copy-paste errors passing mismatched record pairs.
Related errors
- Cannot add record: use SetRecords() for {type} record.
- Cannot update record: use SetRecords() for {type} record
- Cannot update record: the old record does not exists.
- DNS application already exists: {application.Name}
- The application name contains an invalid character: {invalid
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/579b560848bbee59.
Report an issue: GitHub.