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

  1. Set the SOA record on the parent ForwarderZone (the apex), not on the ForwarderSubDomainZone.
  2. Add a zone-type check: skip SOA operations on sub-domain zones.
  3. 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

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


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