TechnitiumSoftware/DnsServer · warning · DnsServerException

Failed to update DNSKEY TTL. Please try again.

Error message

Failed to update DNSKEY TTL. Please try again.

What it means

Thrown by UpdateDnsKeyTtl() when TrySetRecords for the rebuilt DNSKEY RRset returns false. By this point the request passed the signed-zone and stable-key checks, so the failure is in the record-store layer replacing the DNSKEY records. The message explicitly asks to retry, indicating the failure is expected to be transient rather than a permanent config problem.

Source

Thrown at DnsServerCore/Dns/Zones/PrimaryZone.cs:2481

                }
            }

            if (!_entries.TryGetValue(DnsResourceRecordType.DNSKEY, out IReadOnlyList<DnsResourceRecord> dnsKeyRecords))
                throw new InvalidOperationException();

            DnsResourceRecord[] newDnsKeyRecords = new DnsResourceRecord[dnsKeyRecords.Count];

            for (int i = 0; i < dnsKeyRecords.Count; i++)
            {
                DnsResourceRecord dnsKeyRecord = dnsKeyRecords[i];
                newDnsKeyRecords[i] = new DnsResourceRecord(dnsKeyRecord.Name, DnsResourceRecordType.DNSKEY, DnsClass.IN, dnsKeyTtl, dnsKeyRecord.RDATA);
            }

            List<DnsResourceRecord> addedRecords = new List<DnsResourceRecord>();
            List<DnsResourceRecord> deletedRecords = new List<DnsResourceRecord>();

            if (!TrySetRecords(DnsResourceRecordType.DNSKEY, newDnsKeyRecords, out IReadOnlyList<DnsResourceRecord> deletedDnsKeyRecords))
                throw new DnsServerException("Failed to update DNSKEY TTL. Please try again.");

            addedRecords.AddRange(newDnsKeyRecords);
            deletedRecords.AddRange(deletedDnsKeyRecords);

            IReadOnlyList<DnsResourceRecord> newRRSigRecords = SignRRSet(newDnsKeyRecords);
            if (newRRSigRecords.Count > 0)
            {
                AddOrUpdateRRSigRecords(newRRSigRecords, out IReadOnlyList<DnsResourceRecord> deletedRRSigRecords);

                addedRecords.AddRange(newRRSigRecords);
                deletedRecords.AddRange(deletedRRSigRecords);
            }

            CommitAndIncrementSerial(deletedRecords, addedRecords);
            TriggerNotify();
        }

        #endregion

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Retry UpdateDnsKeyTtl after a short backoff; the message indicates a transient failure.
  2. Ensure no concurrent record writers (other API calls, replication, zone transfer notify) are mutating the zone during the update.
  3. If retries consistently fail, inspect the server log (the store layer failure is logged separately) for the underlying I/O or lock error.

Example fix

// before
zone.UpdateDnsKeyTtl(desiredTtl);

// after
for (int attempt = 0; attempt < 3; attempt++)
{
    try { zone.UpdateDnsKeyTtl(desiredTtl); break; }
    catch (DnsServerException) when (attempt < 2) { Thread.Sleep(Backoff(attempt)); }
}
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

null

Try / catch

for (int attempt = 0; attempt < 3; attempt++)
{
    try { zone.UpdateDnsKeyTtl(ttl); return; }
    catch (DnsServerException ex) when (ex.Message.StartsWith("Failed to update DNSKEY TTL") && attempt < 2)
    { Thread.Sleep(TimeSpan.FromSeconds(1 << attempt)); }
}

Prevention

When it happens

Trigger: TrySetRecords(DnsResourceRecordType.DNSKEY, newDnsKeyRecords, ...) returns false while replacing the existing DNSKEY RRset during a TTL update. Typically a concurrent modification, a transient I/O or store error, or an inability to commit the new RRset atomically.

Common situations: Another thread or peer is concurrently modifying the same zone's records; the backing store is temporarily locked or out of space; a race between zone save/flush and the TTL update.

Related errors


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