{"record":{"id":"579b560848bbee59","repo":"TechnitiumSoftware/DnsServer","slug":"old-and-new-record-types-do-not-match","errorCode":null,"errorMessage":"Old and new record types do not match.","messagePattern":"Old and new record types do not match\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/AuthZone.cs","lineNumber":858,"sourceCode":"        }\n\n        public virtual bool DeleteRecords(DnsResourceRecordType type)\n        {\n            return _entries.TryRemove(type, out _);\n        }\n\n        public virtual bool DeleteRecord(DnsResourceRecordType type, DnsResourceRecordData rdata)\n        {\n            return TryDeleteRecord(type, rdata, out _);\n        }\n\n        public virtual void UpdateRecord(DnsResourceRecord oldRecord, DnsResourceRecord newRecord)\n        {\n            if (oldRecord.Type == DnsResourceRecordType.SOA)\n                throw new InvalidOperationException(\"Cannot update record: use SetRecords() for \" + oldRecord.Type.ToString() + \" record\");\n\n            if (oldRecord.Type != newRecord.Type)\n                throw new InvalidOperationException(\"Old and new record types do not match.\");\n\n            if (!DeleteRecord(oldRecord.Type, oldRecord.RDATA))\n                throw new DnsWebServiceException(\"Cannot update record: the old record does not exists.\");\n\n            AddRecord(newRecord);\n        }\n\n        public virtual IReadOnlyList<DnsResourceRecord> QueryRecords(DnsResourceRecordType type, bool dnssecOk)\n        {\n            switch (type)\n            {\n                case DnsResourceRecordType.APP:\n                case DnsResourceRecordType.FWD:\n                case DnsResourceRecordType.NSEC:\n                case DnsResourceRecordType.NSEC3:\n                    {\n                        //return only exact type if exists\n                        if (_entries.TryGetValue(type, out IReadOnlyList<DnsResourceRecord> existingRecords))","sourceCodeStart":840,"sourceCodeEnd":876,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/AuthZone.cs#L840-L876","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nzone.UpdateRecord(oldARecord, newAaaaRecord); // type mismatch\n\n// after\nzone.DeleteRecord(oldARecord.Type, oldARecord.RDATA);\nzone.AddRecord(newAaaaRecord);","handlingStrategy":"validation","validationCode":"if (oldRecord.Type != newRecord.Type)\n    throw new ArgumentException($\"Record type change not supported by UpdateRecord (old: {oldRecord.Type}, new: {newRecord.Type}). Use DeleteRecord + AddRecord instead.\");\nzone.UpdateRecord(oldRecord, newRecord);","typeGuard":"static bool TypesMatch(DnsResourceRecord oldRecord, DnsResourceRecord newRecord)\n    => oldRecord.Type == newRecord.Type;","tryCatchPattern":null,"preventionTips":["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."],"tags":["dns","record-management","validation","auth-zone"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}