TechnitiumSoftware/DnsServer · error · DnsServerException
Cannot update record: TTL cannot be greater than SOA EXPIRE.
Error message
Cannot update record: TTL cannot be greater than SOA EXPIRE.
What it means
Thrown by PrimaryZone.UpdateRecord (default case) when newRecord.OriginalTtlValue exceeds GetZoneSoaExpire(). Same TTL cap as AddRecord (error 580): records must not outlive the zone's SOA EXPIRE window. DnsServerException indicates invalid data rather than API misuse.
Source
Thrown at DnsServerCore/Dns/Zones/PrimaryZone.cs:2762
case DnsResourceRecordType.SOA:
throw new InvalidOperationException("Cannot update record: use SetRecords() for " + oldRecord.Type.ToString() + " record");
case DnsResourceRecordType.DNSKEY:
case DnsResourceRecordType.RRSIG:
case DnsResourceRecordType.NSEC:
case DnsResourceRecordType.NSEC3PARAM:
case DnsResourceRecordType.NSEC3:
throw new InvalidOperationException("Cannot update DNSSEC records.");
default:
if (oldRecord.Type != newRecord.Type)
throw new InvalidOperationException("Old and new record types do not match.");
if ((_dnssecStatus != AuthZoneDnssecStatus.Unsigned) && newRecord.GetAuthGenericRecordInfo().Disabled)
throw new DnsServerException("Cannot update record: disabling records in a signed zones is not supported.");
if (newRecord.OriginalTtlValue > GetZoneSoaExpire())
throw new DnsServerException("Cannot update record: TTL cannot be greater than SOA EXPIRE.");
if (!TryDeleteRecord(oldRecord.Type, oldRecord.RDATA, out DnsResourceRecord deletedRecord))
throw new DnsServerException("Cannot update record: the record does not exists to be updated.");
AddRecord(newRecord, out IReadOnlyList<DnsResourceRecord> addedRecords, out IReadOnlyList<DnsResourceRecord> deletedRecords);
List<DnsResourceRecord> allDeletedRecords = new List<DnsResourceRecord>(deletedRecords.Count + 1);
allDeletedRecords.Add(deletedRecord);
allDeletedRecords.AddRange(deletedRecords);
CommitAndIncrementSerial(allDeletedRecords, addedRecords);
if (_dnssecStatus != AuthZoneDnssecStatus.Unsigned)
UpdateDnssecRecordsFor(this, oldRecord.Type);
TriggerNotify();
break;
}View on GitHub (pinned to d0484b6c1e)
Solutions
- Clamp newRecord.OriginalTtlValue to <= GetZoneSoaExpire() before updating.
- Increase SOA EXPIRE via SetRecords(SOA, ...) if the larger TTL is required.
- Validate TTL against the cap in the same helper used by AddRecord.
Example fix
// before
zone.UpdateRecord(oldRecord, newRecord); // TTL too high
// after
uint cap = zone.GetZoneSoaExpire();
if (newRecord.OriginalTtlValue > cap)
newRecord = WithTtl(newRecord, cap);
zone.UpdateRecord(oldRecord, newRecord); Defensive patterns
Strategy: validation
Validate before calling
uint cap = zone.GetZoneSoaExpire();
if (newRecord.OriginalTtlValue > cap)
newRecord = WithOriginalTtl(newRecord, cap);
zone.UpdateRecord(oldRecord, newRecord); Type guard
static bool TtlWithinSoaExpire(PrimaryZone zone, DnsResourceRecord r) =>
r.OriginalTtlValue <= zone.GetZoneSoaExpire(); Try / catch
null
Prevention
- Reuse the same TTL-clamp helper for AddRecord and UpdateRecord.
- Surface SOA EXPIRE in record-edit UIs so users see the ceiling.
When it happens
Trigger: Calling zone.UpdateRecord(oldRecord, newRecord) where newRecord.OriginalTtlValue (seconds) is greater than the zone SOA EXPIRE.
Common situations: Raising a TTL during an edit; migrating records with 7-day TTLs into a zone with a small EXPIRE; unit vs seconds mismatch.
Related errors
- Cannot add record: TTL cannot be greater than SOA EXPIRE.
- Cannot add record: TTL cannot be greater than SOA EXPIRE.
- Cannot update record: TTL cannot be greater than SOA EXPIRE.
- Cannot set record: TTL cannot be greater than SOA EXPIRE.
- Cannot set records: TTL cannot be greater than SOA EXPIRE.
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/c092029b514a50de.
Report an issue: GitHub.