{"record":{"id":"eb962071da94477a","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-add-secondary-node-the-cluster-is-not-i","errorCode":null,"errorMessage":"Failed to add Secondary node: the Cluster is not initialized.","messagePattern":"Failed to add Secondary node: the Cluster is not initialized\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":686,"sourceCode":"\n        public void DeleteCluster(bool forceDelete)\n        {\n            if (!ClusterInitialized)\n                throw new DnsServerException(\"Failed to delete Cluster: the Cluster is not initialized.\");\n\n            if (GetSelfNode().Type != ClusterNodeType.Primary)\n                throw new DnsServerException(\"Failed to delete Cluster: only a Primary node can delete the Cluster.\");\n\n            if (!forceDelete && (_clusterNodes.Count > 1))\n                throw new DnsServerException(\"Failed to delete Cluster: please remove all Secondary nodes before deleting the Cluster.\");\n\n            DeleteAllClusterConfig();\n        }\n\n        public ClusterNode JoinCluster(int secondaryNodeId, Uri secondaryNodeUrl, IReadOnlyList<IPAddress> secondaryNodeIpAddresses, X509Certificate2 secondaryNodeCertificate)\n        {\n            if (!ClusterInitialized)\n                throw new DnsServerException(\"Failed to add Secondary node: the Cluster is not initialized.\");\n\n            if (GetSelfNode().Type != ClusterNodeType.Primary)\n                throw new DnsServerException(\"Failed to add Secondary node: only a Primary node can add a Secondary node to the Cluster.\");\n\n            string secondaryNodeDomain = secondaryNodeUrl.Host.ToLowerInvariant();\n\n            if (!secondaryNodeDomain.EndsWith(\".\" + _clusterDomain, StringComparison.OrdinalIgnoreCase))\n                throw new DnsServerException(\"Failed to add Secondary node: the Secondary node domain name must be a subdomain of the Cluster domain name.\");\n\n            IReadOnlyDictionary<int, ClusterNode> existingClusterNodes = _clusterNodes;\n\n            //validate for duplicate names\n            foreach (KeyValuePair<int, ClusterNode> existingClusterNode in existingClusterNodes)\n            {\n                if (existingClusterNode.Value.Name.Equals(secondaryNodeUrl.Host, StringComparison.OrdinalIgnoreCase))\n                    throw new DnsServerException(\"Failed to add Secondary node: A node with the same DNS Server Domain Name already exists in the Cluster. Please try again after changing the Secondary node's DNS Server Domain Name.\");\n            }\n","sourceCodeStart":668,"sourceCodeEnd":704,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L668-L704","documentation":"Thrown by JoinCluster when ClusterInitialized is false. JoinCluster adds a Secondary node to an existing cluster, which requires the cluster to already be set up with a Primary node, a primary zone, and a catalog zone. Without an initialized cluster there is nothing to join to.","triggerScenarios":"JoinCluster(secondaryNodeId, secondaryNodeUrl, ...) is called on a server where _clusterNodes is null or empty. The guard at line 685 fires before any Secondary-node logic runs.","commonSituations":"Calling JoinCluster on the wrong server (e.g., on a Secondary or a fresh server instead of the initialized Primary); the Primary's cluster config was lost or not loaded; calling join before initialize completed.","solutions":["Initialize the cluster on the Primary node first via InitializeCluster, then call JoinCluster on that same Primary.","Check ClusterManager.ClusterInitialized before calling JoinCluster.","Verify the server's cluster config file loaded correctly on startup."],"exampleFix":"// before\n_dnsWebService.ClusterManager.JoinCluster(nodeId, nodeUrl, nodeIps, cert);\n// after\nif (!_dnsWebService.ClusterManager.ClusterInitialized)\n    throw new InvalidOperationException(\"Initialize the cluster on the Primary node first.\");\n_dnsWebService.ClusterManager.JoinCluster(nodeId, nodeUrl, nodeIps, cert);","handlingStrategy":"validation","validationCode":"if (!_dnsWebService.ClusterManager.ClusterInitialized)\n    throw new InvalidOperationException(\"Initialize the cluster on the Primary node before joining a Secondary.\");\n_dnsWebService.ClusterManager.JoinCluster(nodeId, nodeUrl, nodeIps, cert);","typeGuard":"static bool CanJoinCluster(ClusterManager cm) => cm.ClusterInitialized;","tryCatchPattern":"try\n{\n    _dnsWebService.ClusterManager.JoinCluster(nodeId, nodeUrl, nodeIps, cert);\n}\ncatch (DnsServerException ex) when (ex.Message.Contains(\"add Secondary node\") && ex.Message.Contains(\"not initialized\"))\n{\n    throw new InvalidOperationException(\"The cluster is not initialized. Run InitializeCluster on the Primary first.\", ex);\n}","preventionTips":["Initialize the cluster on the Primary before attempting any JoinCluster calls.","Check ClusterInitialized in your orchestration before issuing join requests.","Verify the cluster config file loaded on startup if initialization is unexpectedly missing."],"tags":["cluster","join","validation","not-initialized"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}