TechnitiumSoftware/DnsServer · error · DnsWebServiceException

Cannot update record: the old record does not exists.

Error message

Cannot update record: the old record does not exists.

What it means

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).

Source

Thrown at DnsServerCore/Dns/Zones/AuthZone.cs:861

        {
            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))
                        {
                            IReadOnlyList<DnsResourceRecord> filteredRecords = FilterDisabledRecords(type, existingRecords);
                            if (filteredRecords.Count > 0)

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Re-read the current record from the zone (QueryRecords) before retrying the update to get fresh rdata.
  2. 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.
  3. Use SetRecords instead of UpdateRecord if you want to replace by type without needing the exact old rdata.

Example fix

// before
zone.UpdateRecord(staleOldRecord, newRecord);
// throws: old record does not exist (was modified concurrently)

// after
var current = zone.QueryRecords(staleOldRecord.Type, false);
var match = current.FirstOrDefault(r => r.RDATA.Equals(staleOldRecord.RDATA));
if (match != null)
    zone.UpdateRecord(match, newRecord);
else
    zone.AddRecord(newRecord); // or report conflict
Defensive patterns

Strategy: validation

Validate before calling

// Verify old record exists before attempting update
var current = zone.QueryRecords(oldRecord.Type, false);
bool exists = current.Any(r => r.RDATA.Equals(oldRecord.RDATA));
if (!exists)
    throw new InvalidOperationException("Cannot update: the old record was not found. It may have been modified concurrently.");
zone.UpdateRecord(oldRecord, newRecord);

Try / catch

try { zone.UpdateRecord(oldRecord, newRecord); }
catch (DnsWebServiceException ex) when (ex.Message.Contains("does not exists"))
{ /* re-read current records, surface concurrency conflict to user, or retry */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13). Data as JSON: /api/errors/3a4ea335ea1f8021. Report an issue: GitHub.