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

  1. Route SOA record changes through SetRecords(zoneName, SOA, new[] { soaRecord }) instead of UpdateRecord.
  2. In generic record-handling code, add a type check: if record type is SOA, branch to the SOA-specific update path.
  3. 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

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


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