{"record":{"id":"63d3d8890df43732","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-update-record-use-setrecords-for-type","errorCode":null,"errorMessage":"Cannot update record: use SetRecords() for {type} record","messagePattern":"Cannot update record: use SetRecords\\(\\) for (.+?) record","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/AuthZone.cs","lineNumber":855,"sourceCode":"            AddRecord(record, out IReadOnlyList<DnsResourceRecord> addedRecords, out _);\n\n            return addedRecords.Count > 0;\n        }\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:","sourceCodeStart":837,"sourceCodeEnd":873,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/AuthZone.cs#L837-L873","documentation":"AuthZone.UpdateRecord rejects SOA record updates with InvalidOperationException. The SOA (Start of Authority) record is a singleton that defines zone-wide parameters (serial, refresh, retry, expire, minimum) and has special semantics for zone transfers and DNSSEC. UpdateRecord performs a delete-then-add sequence that is unsafe for SOA; the library requires SetRecords() which atomically replaces the single SOA record.","triggerScenarios":"Calling UpdateRecord with oldRecord.Type == DnsResourceRecordType.SOA. This occurs when zone-management code attempts to modify SOA parameters (e.g., changing refresh interval or serial number) through the generic UpdateRecord API.","commonSituations":"Zone management UI/API that routes all record edits through a single UpdateRecord handler; scripts adjusting SOA timers; DNSSEC key rollover workflows that attempt SOA updates generically.","solutions":["Use SetRecords(DnsResourceRecordType.SOA, [newSoaRecord]) to replace the SOA record atomically.","Use the zone's dedicated SOA management methods if available (e.g., serial increment, timer adjustment APIs).","Add a type guard before calling UpdateRecord to route SOA records to SetRecords."],"exampleFix":"// before\nzone.UpdateRecord(oldSoaRecord, newSoaRecord);\n// throws: use SetRecords() for SOA record\n\n// after\nzone.SetRecords(DnsResourceRecordType.SOA, new[] { newSoaRecord });","handlingStrategy":"type-guard","validationCode":"if (oldRecord.Type == DnsResourceRecordType.SOA)\n    zone.SetRecords(DnsResourceRecordType.SOA, new[] { newRecord });\nelse\n    zone.UpdateRecord(oldRecord, newRecord);","typeGuard":"static bool CanUpdateRecord(DnsResourceRecordType type)\n    => type != DnsResourceRecordType.SOA;","tryCatchPattern":null,"preventionTips":["Route SOA modifications through SetRecords in all code paths.","Add a type check before UpdateRecord to dispatch SOA correctly.","Use zone-specific SOA management APIs for serial/timer changes."],"tags":["dns","soa","record-management","auth-zone","api-misuse"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}