{"record":{"id":"03b24de1aa35b7af","repo":"TechnitiumSoftware/DnsServer","slug":"zone-must-be-a-primary-secondary-or-forwarder-zo","errorCode":null,"errorMessage":"Zone must be a primary, secondary, or forwarder zone.","messagePattern":"Zone must be a primary, secondary, or forwarder zone\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs","lineNumber":2476,"sourceCode":"                        subDomainZone.AutoUpdateState();\n                }\n            }\n        }\n\n        #endregion\n\n        #region zone transfer / import\n\n        public IReadOnlyList<DnsResourceRecord> QueryZoneTransferRecords(string zoneName)\n        {\n            AuthZoneInfo zoneInfo = GetAuthZoneInfo(zoneName);\n            if (zoneInfo is null)\n                throw new InvalidOperationException(\"Zone was not found: \" + zoneName);\n\n            //primary, secondary, and forwarder zones support zone transfer\n            IReadOnlyList<DnsResourceRecord> soaRecords = zoneInfo.ApexZone.GetRecords(DnsResourceRecordType.SOA);\n            if (soaRecords.Count != 1)\n                throw new InvalidOperationException(\"Zone must be a primary, secondary, or forwarder zone.\");\n\n            DnsResourceRecord soaRecord = soaRecords[0];\n\n            List<DnsResourceRecord> records = new List<DnsResourceRecord>();\n            ListAllZoneRecords(zoneName, records);\n\n            List<DnsResourceRecord> xfrRecords = new List<DnsResourceRecord>(records.Count + 1);\n\n            //start message\n            xfrRecords.Add(soaRecord);\n\n            foreach (DnsResourceRecord record in records)\n            {\n                GenericRecordInfo authRecordInfo = record.GetAuthGenericRecordInfo();\n                if (authRecordInfo.Disabled)\n                    continue;\n\n                switch (record.Type)","sourceCodeStart":2458,"sourceCodeEnd":2494,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs#L2458-L2494","documentation":"Thrown by QueryZoneTransferRecords when the zone exists but has a SOA record count != 1. Full zone transfer (AXFR) requires exactly one SOA record at the apex. Zones without a proper SOA (e.g. Stub zones, Catalog zones, or zones in a corrupted/incomplete state) cannot be transferred. The error message lists the supported types: primary, secondary, forwarder.","triggerScenarios":"Calling QueryZoneTransferRecords on a Stub zone (which has NS records but no SOA), a Catalog zone, or a zone whose SOA record is missing or duplicated due to corruption. The zoneInfo is non-null (passes the null check) but zoneInfo.ApexZone.GetRecords(SOA).Count is 0 or >1.","commonSituations":"Misconfigured zone transfer ACL allowing transfer of stub zones; zone file corruption causing missing or duplicate SOA; catalog zone being queried for AXFR (catalogs use a different transfer mechanism); zone in a partially-loaded state.","solutions":["Check the zone type before transferring: only Primary, Secondary, and Forwarder zones support AXFR.","Verify the zone has exactly one SOA record by querying apex SOA records.","If the zone is a stub or catalog, do not attempt standard zone transfer.","Repair the zone file if SOA is missing or duplicated."],"exampleFix":"// before\nvar xfrRecords = authZoneManager.QueryZoneTransferRecords(zoneName);\n\n// after\nAuthZoneInfo info = authZoneManager.GetAuthZoneInfo(zoneName);\nif (info is null)\n    throw new InvalidOperationException(\"Zone not found.\");\nif (info.Type != AuthZoneType.Primary && info.Type != AuthZoneType.Secondary && info.Type != AuthZoneType.Forwarder)\n    throw new InvalidOperationException($\"Zone type '{info.Type}' does not support AXFR.\");\nvar xfrRecords = authZoneManager.QueryZoneTransferRecords(zoneName);","handlingStrategy":"validation","validationCode":"AuthZoneInfo info = authZoneManager.GetAuthZoneInfo(zoneName);\nif (info is null)\n    throw new InvalidOperationException(\"Zone not found.\");\nif (info.Type != AuthZoneType.Primary && info.Type != AuthZoneType.Secondary && info.Type != AuthZoneType.Forwarder)\n    throw new InvalidOperationException($\"Zone type '{info.Type}' does not support AXFR.\");","typeGuard":"static bool ZoneSupportsAxfr(AuthZoneManager mgr, string zoneName)\n{\n    AuthZoneInfo info = mgr.GetAuthZoneInfo(zoneName);\n    if (info is null) return false;\n    return info.Type is AuthZoneType.Primary or AuthZoneType.Secondary or AuthZoneType.Forwarder;\n}","tryCatchPattern":"try\n{\n    var records = authZoneManager.QueryZoneTransferRecords(zoneName);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"primary, secondary, or forwarder\"))\n{\n    logger.LogWarning(\"AXFR not supported for zone '{Zone}': wrong zone type.\", zoneName);\n}","preventionTips":["Check zone type supports AXFR (Primary, Secondary, Forwarder) before requesting transfer.","Do not attempt AXFR on Stub or Catalog zones.","Verify exactly one SOA record exists at the apex."],"tags":["zone-transfer","axfr","zone-management","soa","validation"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}