{"record":{"id":"3a4ea335ea1f8021","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-update-record-the-old-record-does-not-exis-3a4ea3","errorCode":null,"errorMessage":"Cannot update record: the old record does not exists.","messagePattern":"Cannot update record: the old record does not exists\\.","errorType":"exception","errorClass":"DnsWebServiceException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/AuthZone.cs","lineNumber":861,"sourceCode":"        {\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))\n                        {\n                            IReadOnlyList<DnsResourceRecord> filteredRecords = FilterDisabledRecords(type, existingRecords);\n                            if (filteredRecords.Count > 0)","sourceCodeStart":843,"sourceCodeEnd":879,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/AuthZone.cs#L843-L879","documentation":"AuthZone.UpdateRecord calls DeleteRecord(oldType, oldRdata) to remove the old record before adding the new one. If DeleteRecord returns false — meaning no record matching the exact type and rdata was found in _entries — it throws DnsWebServiceException. This indicates the old record was already deleted, was never present, or its rdata has drifted since the caller last read it (concurrent modification).","triggerScenarios":"Calling UpdateRecord with an oldRecord whose rdata no longer exists in the zone (was deleted by another process, expired, or the caller is working from stale data). The TryDeleteRecord method only succeeds when the exact rdata match is found.","commonSituations":"Concurrent zone modifications (another admin or zone transfer changed the record between read and update); stale UI state (record list was loaded, record changed server-side, then update submitted); race conditions in automated provisioning; retrying a failed update after the record was already modified.","solutions":["Re-read the current record from the zone (QueryRecords) before retrying the update to get fresh rdata.","Implement optimistic concurrency: if the old record is gone, treat it as a conflict and surface a 'record was modified by another process' message to the user.","Use SetRecords instead of UpdateRecord if you want to replace by type without needing the exact old rdata."],"exampleFix":"// before\nzone.UpdateRecord(staleOldRecord, newRecord);\n// throws: old record does not exist (was modified concurrently)\n\n// after\nvar current = zone.QueryRecords(staleOldRecord.Type, false);\nvar match = current.FirstOrDefault(r => r.RDATA.Equals(staleOldRecord.RDATA));\nif (match != null)\n    zone.UpdateRecord(match, newRecord);\nelse\n    zone.AddRecord(newRecord); // or report conflict","handlingStrategy":"validation","validationCode":"// Verify old record exists before attempting update\nvar current = zone.QueryRecords(oldRecord.Type, false);\nbool exists = current.Any(r => r.RDATA.Equals(oldRecord.RDATA));\nif (!exists)\n    throw new InvalidOperationException(\"Cannot update: the old record was not found. It may have been modified concurrently.\");\nzone.UpdateRecord(oldRecord, newRecord);","typeGuard":null,"tryCatchPattern":"try { zone.UpdateRecord(oldRecord, newRecord); }\ncatch (DnsWebServiceException ex) when (ex.Message.Contains(\"does not exists\"))\n{ /* re-read current records, surface concurrency conflict to user, or retry */ }","preventionTips":["Re-read the current record state before updating to detect concurrent modifications.","Implement optimistic concurrency control with versioning or timestamp checks.","Handle the 'old record not found' case gracefully in UI/API code with a clear conflict message."],"tags":["dns","record-management","concurrency","stale-data","auth-zone"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}