{"record":{"id":"5dbdfb58f633602d","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-set-soa-record-on-sub-domain","errorCode":null,"errorMessage":"Cannot set SOA record on sub domain.","messagePattern":"Cannot set SOA record on sub domain\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/ForwarderSubDomainZone.cs","lineNumber":51,"sourceCode":"\n        #region constructor\n\n        public ForwarderSubDomainZone(ForwarderZone forwarderZone, string name)\n            : base(forwarderZone, name)\n        {\n            _forwarderZone = forwarderZone;\n        }\n\n        #endregion\n\n        #region public\n\n        public override void SetRecords(DnsResourceRecordType type, IReadOnlyList<DnsResourceRecord> records)\n        {\n            switch (type)\n            {\n                case DnsResourceRecordType.SOA:\n                    throw new InvalidOperationException(\"Cannot set SOA record on sub domain.\");\n\n                case DnsResourceRecordType.DS:\n                case DnsResourceRecordType.DNSKEY:\n                case DnsResourceRecordType.RRSIG:\n                case DnsResourceRecordType.NSEC:\n                case DnsResourceRecordType.NSEC3PARAM:\n                case DnsResourceRecordType.NSEC3:\n                    throw new InvalidOperationException(\"Cannot set DNSSEC records.\");\n\n                default:\n                    if (records[0].OriginalTtlValue > _forwarderZone.GetZoneSoaExpire())\n                        throw new DnsServerException(\"Cannot set records: TTL cannot be greater than SOA EXPIRE.\");\n\n                    if (!TrySetRecords(type, records, out IReadOnlyList<DnsResourceRecord> deletedRecords))\n                        throw new DnsServerException(\"Cannot set records. Please try again.\");\n\n                    _forwarderZone.CommitAndIncrementSerial(deletedRecords, records);\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/ForwarderSubDomainZone.cs#L33-L69","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nsubDomainZone.SetRecords(DnsResourceRecordType.SOA, soaRecords);\n// throws: Cannot set SOA record on sub domain\n\n// after\n// set SOA on the parent forwarder zone apex instead:\nforwarderZone.SetRecords(DnsResourceRecordType.SOA, soaRecords);\n// skip SOA for sub-domain nodes","handlingStrategy":"type-guard","validationCode":"if (zone is ForwarderSubDomainZone && type == DnsResourceRecordType.SOA)\n    throw new InvalidOperationException(\"Cannot set SOA on a forwarder sub-domain. Set SOA on the parent forwarder zone apex.\");\nzone.SetRecords(type, records);","typeGuard":"static bool CanSetSoa(Zone zone) => zone is not ForwarderSubDomainZone;","tryCatchPattern":null,"preventionTips":["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."],"tags":["dns","soa","forwarder-zone","subdomain","zone-hierarchy"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}