{"record":{"id":"6ce1144a38529648","repo":"TechnitiumSoftware/DnsServer","slug":"zone-must-be-a-primary-or-forwarder-type-apexzon","errorCode":null,"errorMessage":"Zone must be a primary or forwarder type: {apexZone}","messagePattern":"Zone must be a primary or forwarder type: (.+?)","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs","lineNumber":3067,"sourceCode":"            condensedRecords.AddRange(deletedGlueRecords);\n\n            condensedRecords.Add(lastAddedSoaRecord);\n            condensedRecords.AddRange(addedRecords);\n            condensedRecords.AddRange(addedGlueRecords);\n\n            condensedRecords.Add(lastSoaRecord);\n\n            return condensedRecords;\n        }\n\n        internal void ImportRecords(string zoneName, IReadOnlyList<DnsResourceRecord> records, bool overwriteRecords, bool overwriteZone, bool overwriteSoaSerial)\n        {\n            _ = _root.FindZone(zoneName, out _, out _, out ApexZone apexZone, out _);\n            if ((apexZone is null) || !apexZone.Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase))\n                throw new DnsServerException(\"No such zone was found: \" + zoneName);\n\n            if ((apexZone is not PrimaryZone) && (apexZone is not ForwarderZone))\n                throw new DnsServerException(\"Zone must be a primary or forwarder type: \" + apexZone.ToString());\n\n            if (overwriteZone)\n            {\n                //remove all existing records from the zone\n                DeleteAllRecords(zoneName);\n\n                overwriteRecords = true; //set to true for optimization\n            }\n\n            List<DnsResourceRecord> soaRRSet = null;\n\n            foreach (KeyValuePair<string, Dictionary<DnsResourceRecordType, List<DnsResourceRecord>>> zoneEntry in DnsResourceRecord.GroupRecords(records))\n            {\n                if (zoneName.Equals(zoneEntry.Key, StringComparison.OrdinalIgnoreCase))\n                {\n                    foreach (KeyValuePair<DnsResourceRecordType, List<DnsResourceRecord>> rrsetEntry in zoneEntry.Value)\n                    {\n                        switch (rrsetEntry.Key)","sourceCodeStart":3049,"sourceCodeEnd":3085,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs#L3049-L3085","documentation":"Thrown by ImportRecords after the zone is found but it is neither a PrimaryZone nor a ForwarderZone. ImportRecords only writes records into primary or forwarder zones because those are the authoritative, writable zone types; importing into a secondary/cache/other type is rejected. The offending zone's type is included in the message.","triggerScenarios":"Calling ImportRecords against a SecondaryZone, StubZone, CacheZone, or blocked zone; trying to bulk-load records into a zone that derives its data from a master rather than local config.","commonSituations":"Mistakenly importing a primary-zone backup into a zone that was recreated as secondary; automation that imports into whichever zone matches a name without checking its type.","solutions":["Convert the target zone to a primary (or forwarder) zone, or import into an existing primary/forwarder zone.","Check the zone's Type property before calling ImportRecords and skip or convert non-primary/forwarder zones.","Re-add the zone as PrimaryZone before importing the records."],"exampleFix":"// before\nserver.AuthZoneManager.ImportRecords(\"example.com\", records, true, false, false); // zone is SecondaryZone -> throws\n// after\n// (re)create as primary, then import\nserver.AuthZoneManager.DeleteZone(\"example.com\");\nserver.AuthZoneManager.AddPrimaryZone(\"example.com\");\nserver.AuthZoneManager.ImportRecords(\"example.com\", records, true, false, false);","handlingStrategy":"validation","validationCode":"ApexZone apex = FindApex(zoneName);\nif (apex is not PrimaryZone && apex is not ForwarderZone)\n    throw new InvalidOperationException($\"Zone '{zoneName}' is {apex?.GetType().Name}; convert to primary/forwarder before import.\");","typeGuard":"static bool IsImportable(ApexZone zone) => zone is PrimaryZone || zone is ForwarderZone;","tryCatchPattern":"try\n{\n    server.AuthZoneManager.ImportRecords(zoneName, records, true, false, false);\n}\ncatch (DnsServerException ex) when (ex.Message.Contains(\"primary or forwarder type\"))\n{\n    // convert to primary then import\n    RecreateAsPrimary(zoneName);\n    server.AuthZoneManager.ImportRecords(zoneName, records, true, false, false);\n}","preventionTips":["Check the zone's runtime type before calling ImportRecords.","Keep an inventory mapping zone name -> type so imports target the right type.","When restoring backups, recreate zones as the same type they were exported from.","Automate imports with a type guard rather than assuming primary."],"tags":["dns","zone-import","zone-management","validation"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}