TechnitiumSoftware/DnsServer · error · InvalidOperationException
Cannot set SOA record on sub domain.
Error message
Cannot set SOA record on sub domain.
What it means
ForwarderSubDomainZone.SetRecords rejects SOA records with InvalidOperationException. A ForwarderSubDomainZone represents a sub-domain delegation within a forwarder zone — it is not a zone apex and therefore cannot have its own SOA record. The SOA belongs to the parent forwarder zone. Allowing a sub-domain to have its own SOA would violate DNS zone hierarchy rules (RFC 1034 section 4.2.1).
Source
Thrown at DnsServerCore/Dns/Zones/ForwarderSubDomainZone.cs:51
#region constructor
public ForwarderSubDomainZone(ForwarderZone forwarderZone, string name)
: base(forwarderZone, name)
{
_forwarderZone = forwarderZone;
}
#endregion
#region public
public override void SetRecords(DnsResourceRecordType type, IReadOnlyList<DnsResourceRecord> records)
{
switch (type)
{
case DnsResourceRecordType.SOA:
throw new InvalidOperationException("Cannot set SOA record on sub domain.");
case DnsResourceRecordType.DS:
case DnsResourceRecordType.DNSKEY:
case DnsResourceRecordType.RRSIG:
case DnsResourceRecordType.NSEC:
case DnsResourceRecordType.NSEC3PARAM:
case DnsResourceRecordType.NSEC3:
throw new InvalidOperationException("Cannot set DNSSEC records.");
default:
if (records[0].OriginalTtlValue > _forwarderZone.GetZoneSoaExpire())
throw new DnsServerException("Cannot set records: TTL cannot be greater than SOA EXPIRE.");
if (!TrySetRecords(type, records, out IReadOnlyList<DnsResourceRecord> deletedRecords))
throw new DnsServerException("Cannot set records. Please try again.");
_forwarderZone.CommitAndIncrementSerial(deletedRecords, records);
View on GitHub (pinned to d0484b6c1e)
Solutions
- Set the SOA record on the parent ForwarderZone (the apex), not on the ForwarderSubDomainZone.
- Add a zone-type check: skip SOA operations on sub-domain zones.
- Filter SOA records out when applying records to sub-domain nodes.
Example fix
// before subDomainZone.SetRecords(DnsResourceRecordType.SOA, soaRecords); // throws: Cannot set SOA record on sub domain // after // set SOA on the parent forwarder zone apex instead: forwarderZone.SetRecords(DnsResourceRecordType.SOA, soaRecords); // skip SOA for sub-domain nodes
Defensive patterns
Strategy: type-guard
Validate before calling
if (zone is ForwarderSubDomainZone && type == DnsResourceRecordType.SOA)
throw new InvalidOperationException("Cannot set SOA on a forwarder sub-domain. Set SOA on the parent forwarder zone apex.");
zone.SetRecords(type, records); Type guard
static bool CanSetSoa(Zone zone) => zone is not ForwarderSubDomainZone;
Prevention
- Check zone type before setting SOA — sub-domain zones cannot have their own SOA.
- Route SOA operations to the zone apex (parent forwarder zone), not sub-domain nodes.
- Filter SOA records when applying records to non-apex zone nodes.
When it happens
Trigger: Calling SetRecords(DnsResourceRecordType.SOA, records) on a ForwarderSubDomainZone instance. Occurs when zone-management code attempts to set SOA on a sub-domain node of a forwarder zone rather than on the zone apex.
Common situations: Generic zone-management code that applies SOA settings to all zone nodes including sub-domains; importing zone data where SOA records are pushed to all nodes; scripts that iterate zone nodes and set SOA uniformly; misidentifying a sub-domain node as the zone apex.
Related errors
- Zone does not contain SOA record.
- Current SOA serial does not match with the IXFR difference s
- Cannot update record: use SetRecords() for {type} record
- Invalid SOA record.
- Cannot update record: use SetRecords() for {0} record
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/5dbdfb58f633602d.
Report an issue: GitHub.