TechnitiumSoftware/DnsServer · error · DnsServerException
Cannot update record: use SetRecords() for updating SOA reco
Error message
Cannot update record: use SetRecords() for updating SOA record.
What it means
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.
Source
Thrown at DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs:2308
if (authZone is SubDomainZone subDomainZone)
subDomainZone.AutoUpdateState();
return true;
}
return false;
}
public void UpdateRecord(string zoneName, DnsResourceRecord oldRecord, DnsResourceRecord newRecord)
{
ValidateIfDomainBelongsToZone(zoneName, oldRecord.Name);
ValidateIfDomainBelongsToZone(zoneName, newRecord.Name);
if (oldRecord.Type != newRecord.Type)
throw new DnsServerException("Cannot update record: new record must be of same type.");
if (oldRecord.Type == DnsResourceRecordType.SOA)
throw new DnsServerException("Cannot update record: use SetRecords() for updating SOA record.");
if (!_root.TryGet(zoneName, oldRecord.Name, out AuthZone authZone))
throw new DnsServerException("Cannot update record: zone '" + zoneName + "' does not exists.");
switch (oldRecord.Type)
{
case DnsResourceRecordType.CNAME:
case DnsResourceRecordType.DNAME:
case DnsResourceRecordType.APP:
if (oldRecord.Name.Equals(newRecord.Name, StringComparison.OrdinalIgnoreCase))
{
authZone.SetRecords(newRecord.Type, new DnsResourceRecord[] { newRecord });
if (authZone is SubDomainZone subDomainZone)
subDomainZone.AutoUpdateState();
}
else
{View on GitHub (pinned to d0484b6c1e)
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).
Example fix
// before (fails: SOA via UpdateRecord)
authZoneManager.UpdateRecord("example.com", oldSoaRecord, newSoaRecord);
// after (use SetRecords for SOA)
authZoneManager.SetRecords("example.com", DnsResourceRecordType.SOA, new[] { newSoaRecord }); Defensive patterns
Strategy: validation
Validate before calling
if (oldRecord.Type == DnsResourceRecordType.SOA)
throw new InvalidOperationException("Use SetRecords() for SOA record updates, not UpdateRecord()."); Type guard
static bool IsSoaRecord(DnsResourceRecord record)
=> record.Type == DnsResourceRecordType.SOA; Try / catch
try
{
authZoneManager.UpdateRecord(zoneName, oldRecord, newRecord);
}
catch (DnsServerException ex) when (ex.Message.Contains("use SetRecords() for updating SOA"))
{
authZoneManager.SetRecords(zoneName, DnsResourceRecordType.SOA, new[] { newRecord });
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot update record: new record must be of same type.
- Cannot update record: zone '{zoneName}' does not exists.
- Cannot update record: the old record does not exists.
- Zone must be a primary, secondary, or forwarder zone.
- No SOA record was found for IXFR.
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/06cf33117516fbc7.
Report an issue: GitHub.