{"record":{"id":"a5d5a36ad66be22f","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-set-soa-record-on-sub-domain-a5d5a3","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/PrimarySubDomainZone.cs","lineNumber":80,"sourceCode":"                    case DnsResourceRecordType.ANAME:\n                    case DnsResourceRecordType.APP:\n                        throw new DnsServerException(\"The record type is not supported by DNSSEC signed primary zones.\");\n\n                    default:\n                        foreach (DnsResourceRecord record in records)\n                        {\n                            if (record.GetAuthGenericRecordInfo().Disabled)\n                                throw new DnsServerException(\"Cannot set records: disabling records in a signed zones is not supported.\");\n                        }\n\n                        break;\n                }\n            }\n\n            switch (type)\n            {\n                case DnsResourceRecordType.SOA:\n                    throw new InvalidOperationException(\"Cannot set SOA record on sub domain.\");\n\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                case DnsResourceRecordType.FWD:\n                    throw new DnsServerException(\"The record type is not supported by primary zones.\");\n\n                default:\n                    if (records[0].OriginalTtlValue > _primaryZone.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","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs#L62-L98","documentation":"Thrown by PrimarySubDomainZone.SetRecords() when type is DnsResourceRecordType.SOA. A sub-domain zone is a delegated node inside a primary zone and shares its parent's SOA — there is no independent SOA for the sub-domain, and the parent's SOA (serial, timers, name server) is the authoritative one. Setting an SOA at the sub-domain level would create an ambiguous, non-RFC-compliant delegation, so the API hard-rejects it with InvalidOperationException. To change SOA values, edit the parent PrimaryZone's SOA via its own SetRecords(SOA,...).","triggerScenarios":"Calling subDomainZone.SetRecords(DnsResourceRecordType.SOA, records) — e.g. an import that pushes an SOA into every node, or a generic 'set records' routine that does not skip SOA for sub-domains.","commonSituations":"Zone-file importers that write SOA to each node; copy-paste of apex records into a delegation; tooling that treats every zone object as apex-capable.","solutions":["Never call SetRecords(SOA) on a PrimarySubDomainZone; edit the parent PrimaryZone's SOA instead.","Skip SOA (and NS-of-parent) when applying a record set to a sub-domain zone.","If importing, route SOA only to the zone apex, not to delegated sub-nodes."],"exampleFix":"// before\nsubZone.SetRecords(DnsResourceRecordType.SOA, new[] { soaRecord });\n\n// after\n// SOA lives on the parent primary zone\nprimaryZone.SetRecords(DnsResourceRecordType.SOA, new[] { soaRecord });","handlingStrategy":"validation","validationCode":"if (type == DnsResourceRecordType.SOA)\n    throw new InvalidOperationException(\"SOA belongs to the parent primary zone, not the sub-domain.\");\nzone.SetRecords(type, records);","typeGuard":"static bool IsAllowedSubDomainType(DnsResourceRecordType type) => type != DnsResourceRecordType.SOA;","tryCatchPattern":"try { zone.SetRecords(type, records); }\ncatch (InvalidOperationException) when (type == DnsResourceRecordType.SOA) { /* redirect to parent primary zone SetRecords(SOA) */ }","preventionTips":["Never target a PrimarySubDomainZone with SOA; edit the parent PrimaryZone's SOA.","In importers, write SOA only to the zone apex.","Treat sub-domain zones as leaf RRset containers, not apex-capable zones."],"tags":["dns","primary-zone","subdomain","soa-record","invalidoperationexception"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}