{"record":{"id":"a25c844145c643db","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-initialize-cluster-the-zone-clusterzo","errorCode":null,"errorMessage":"Failed to initialize Cluster: the zone '{clusterZoneInfo.Name}' already exists and is not a Primary zone. Please delete the existing zone or use a different Cluster domain name.","messagePattern":"Failed to initialize Cluster: the zone '(.+?)' already exists and is not a Primary zone\\. Please delete the existing zone or use a different Cluster domain name\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":558,"sourceCode":"                else\n                    serverDomain = string.Concat(serverDomain.AsSpan(0, x), \".\", clusterDomain);\n            }\n\n            Uri primaryNodeUrl = new Uri($\"https://{serverDomain}:{_dnsWebService.WebServiceTlsPort}/\");\n\n            ClusterNode selfPrimaryNode = new ClusterNode(this, RandomNumberGenerator.GetInt32(int.MaxValue), primaryNodeUrl, primaryNodeIpAddresses, ClusterNodeType.Primary, ClusterNodeState.Self);\n\n            //create cluster primary zone\n            AuthZoneInfo clusterZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(clusterDomain);\n            if (clusterZoneInfo is null)\n            {\n                clusterZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreatePrimaryZone(clusterDomain);\n                if (clusterZoneInfo is null)\n                    throw new DnsServerException($\"Failed to initialize Cluster: failed to create the Cluster zone '{clusterDomain}'. Please try again.\");\n            }\n            else if (clusterZoneInfo.Type != AuthZoneType.Primary)\n            {\n                throw new DnsServerException($\"Failed to initialize Cluster: the zone '{clusterZoneInfo.Name}' already exists and is not a Primary zone. Please delete the existing zone or use a different Cluster domain name.\");\n            }\n\n            //create cluster catalog zone\n            string clusterCatalogDomain = \"cluster-catalog.\" + clusterDomain;\n\n            AuthZoneInfo clusterCatalogZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(clusterCatalogDomain);\n            if (clusterCatalogZoneInfo is null)\n            {\n                clusterCatalogZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreateCatalogZone(clusterCatalogDomain);\n                if (clusterCatalogZoneInfo is null)\n                    throw new DnsServerException($\"Failed to initialize Cluster: failed to create the Cluster Catalog zone '{clusterCatalogDomain}'. Please try again.\");\n            }\n            else if (clusterCatalogZoneInfo.Type != AuthZoneType.Catalog)\n            {\n                throw new DnsServerException($\"Failed to initialize Cluster: the zone '{clusterCatalogZoneInfo.Name}' already exists and is not a Catalog zone. Please delete the existing zone or use a different Cluster domain name.\");\n            }\n\n            //set cluster primary zone permissions","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L540-L576","documentation":"Thrown by InitializeCluster when the zone matching the requested cluster domain already exists in the AuthZoneManager but its type is not AuthZoneType.Primary (e.g., it is Secondary, Stub, Forwarder, or Catalog). The cluster requires full control over a writable primary zone to store NS/A/AAAA/TLSA records for every node, so a non-primary zone is rejected. The guard is an else-if on the GetAuthZoneInfo lookup result.","triggerScenarios":"InitializeCluster(clusterDomain, ...) is called where clusterDomain names a zone that AuthZoneManager.GetAuthZoneInfo resolves to a non-Primary zone. The primary-creation branch is skipped because the zone is non-null, and the else-if at line 556 fires because clusterZoneInfo.Type != AuthZoneType.Primary.","commonSituations":"Re-using a domain that was previously configured as a secondary or stub zone; leftover zone from a partially torn-down cluster; zone name collision after importing a backup config from another server; manually pre-creating a forwarder zone with the same name.","solutions":["Delete the existing non-primary zone (via the web UI Zones page or AuthZoneManager) so InitializeCluster can create a fresh primary zone, then retry.","Choose a different cluster domain name that does not collide with any existing zone.","If the existing zone should be the cluster zone, convert it to a Primary zone first and retry initialization."],"exampleFix":"// before\n_dnsWebService.ClusterManager.InitializeCluster(\"dns.example.com\", ips, session);\n// after — remove conflicting zone first\nvar zone = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(\"dns.example.com\");\nif (zone is not null && zone.Type != AuthZoneType.Primary)\n    _dnsWebService.DnsServer.AuthZoneManager.DeleteZone(zone.Name);\n_dnsWebService.ClusterManager.InitializeCluster(\"dns.example.com\", ips, session);","handlingStrategy":"validation","validationCode":"// Check for a conflicting non-primary zone before initializing\nstring clusterDomain = \"dns.example.com\";\nvar zone = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(clusterDomain);\nif (zone is not null && zone.Type != AuthZoneType.Primary)\n    throw new InvalidOperationException($\"Zone '{zone.Name}' exists as {zone.Type}; delete it or pick another domain before InitializeCluster.\");\n_dnsWebService.ClusterManager.InitializeCluster(clusterDomain, ips, session);","typeGuard":"static bool IsZoneSafeForClusterInit(AuthZoneInfo zone, string clusterDomain)\n    => zone is null || (zone.Name.Equals(clusterDomain, StringComparison.OrdinalIgnoreCase) && zone.Type == AuthZoneType.Primary);","tryCatchPattern":"try\n{\n    _dnsWebService.ClusterManager.InitializeCluster(clusterDomain, ips, session);\n}\ncatch (DnsServerException ex) when (ex.Message.Contains(\"already exists and is not a Primary zone\"))\n{\n    // surface to user: delete the conflicting zone or change the domain\n    throw new InvalidOperationException(\"Cluster domain conflicts with an existing non-primary zone. Delete it or use a different domain.\", ex);\n}","preventionTips":["Before InitializeCluster, call GetAuthZoneInfo and verify any existing zone is Primary or absent.","Use a unique cluster domain name not previously used for secondary/stub/forwarder zones.","After a failed cluster init, clean up any zones created before retrying."],"tags":["cluster","dns-zone","initialization","primary-zone","zone-conflict"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}