{"record":{"id":"06cf33117516fbc7","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-update-record-use-setrecords-for-updatin","errorCode":null,"errorMessage":"Cannot update record: use SetRecords() for updating SOA record.","messagePattern":"Cannot update record: use SetRecords\\(\\) for updating SOA record\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs","lineNumber":2308,"sourceCode":"                if (authZone is SubDomainZone subDomainZone)\n                    subDomainZone.AutoUpdateState();\n\n                return true;\n            }\n\n            return false;\n        }\n\n        public void UpdateRecord(string zoneName, DnsResourceRecord oldRecord, DnsResourceRecord newRecord)\n        {\n            ValidateIfDomainBelongsToZone(zoneName, oldRecord.Name);\n            ValidateIfDomainBelongsToZone(zoneName, newRecord.Name);\n\n            if (oldRecord.Type != newRecord.Type)\n                throw new DnsServerException(\"Cannot update record: new record must be of same type.\");\n\n            if (oldRecord.Type == DnsResourceRecordType.SOA)\n                throw new DnsServerException(\"Cannot update record: use SetRecords() for updating SOA record.\");\n\n            if (!_root.TryGet(zoneName, oldRecord.Name, out AuthZone authZone))\n                throw new DnsServerException(\"Cannot update record: zone '\" + zoneName + \"' does not exists.\");\n\n            switch (oldRecord.Type)\n            {\n                case DnsResourceRecordType.CNAME:\n                case DnsResourceRecordType.DNAME:\n                case DnsResourceRecordType.APP:\n                    if (oldRecord.Name.Equals(newRecord.Name, StringComparison.OrdinalIgnoreCase))\n                    {\n                        authZone.SetRecords(newRecord.Type, new DnsResourceRecord[] { newRecord });\n\n                        if (authZone is SubDomainZone subDomainZone)\n                            subDomainZone.AutoUpdateState();\n                    }\n                    else\n                    {","sourceCodeStart":2290,"sourceCodeEnd":2326,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs#L2290-L2326","documentation":"Thrown by UpdateRecord when oldRecord.Type is DnsResourceRecordType.SOA. SOA (Start of Authority) records have special semantics (serial number, timers) and must be updated through the dedicated SetRecords() method, not the generic UpdateRecord path. This guard prevents callers from corrupting the SOA through an incompatible code path.","triggerScenarios":"Calling UpdateRecord where either record carries Type == SOA. The method validates type equality first (error 408), then checks for SOA. So this fires only when both oldRecord and newRecord are SOA type but the caller still used UpdateRecord instead of SetRecords.","commonSituations":"Automation script that generically calls UpdateRecord for all record types including SOA; UI edit form that routes SOA edits through the wrong handler; attempting to bump the SOA serial via UpdateRecord.","solutions":["Route SOA record changes through SetRecords(zoneName, SOA, new[] { soaRecord }) instead of UpdateRecord.","In generic record-handling code, add a type check: if record type is SOA, branch to the SOA-specific update path.","Use the zone's built-in SOA update method if available (e.g., IncrementSerial or similar)."],"exampleFix":"// before (fails: SOA via UpdateRecord)\nauthZoneManager.UpdateRecord(\"example.com\", oldSoaRecord, newSoaRecord);\n\n// after (use SetRecords for SOA)\nauthZoneManager.SetRecords(\"example.com\", DnsResourceRecordType.SOA, new[] { newSoaRecord });","handlingStrategy":"validation","validationCode":"if (oldRecord.Type == DnsResourceRecordType.SOA)\n    throw new InvalidOperationException(\"Use SetRecords() for SOA record updates, not UpdateRecord().\");","typeGuard":"static bool IsSoaRecord(DnsResourceRecord record)\n    => record.Type == DnsResourceRecordType.SOA;","tryCatchPattern":"try\n{\n    authZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);\n}\ncatch (DnsServerException ex) when (ex.Message.Contains(\"use SetRecords() for updating SOA\"))\n{\n    authZoneManager.SetRecords(zoneName, DnsResourceRecordType.SOA, new[] { newRecord });\n}","preventionTips":["Branch on record type in generic record handlers: SOA goes to SetRecords.","Never pass SOA records to UpdateRecord.","Document the SOA update path separately in API guides."],"tags":["dns-records","zone-management","soa","validation","record-update"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}