{"record":{"id":"8ad541df0374bade","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-update-primary-node-the-specified-node","errorCode":null,"errorMessage":"Failed to update Primary node: the specified node is the self node and cannot be updated this way.","messagePattern":"Failed to update Primary node: the specified node is the self node and cannot be updated this way\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":1539,"sourceCode":"                        throw new DnsServerException($\"The domain name '{primaryNodeUrl.Host}' does not have an A/AAAA record configured.\");\n\n                    primaryNodeIpAddresses = ipAddresses;\n                }\n                catch (Exception ex)\n                {\n                    throw new DnsServerException($\"Failed to update Primary node: the Primary node domain name '{primaryNodeUrl.Host}' could not be resolved to an IP address.\", ex);\n                }\n            }\n\n            ClusterNode primaryNode;\n\n            if (primaryNodeId < 0)\n                primaryNode = GetPrimaryNode();\n            else if (!_clusterNodes.TryGetValue(primaryNodeId, out primaryNode))\n                throw new DnsServerException(\"Failed to update Primary node: the specified Primary node ID does not exists in the Cluster.\");\n\n            if (primaryNode.State == ClusterNodeState.Self)\n                throw new DnsServerException(\"Failed to update Primary node: the specified node is the self node and cannot be updated this way.\");\n\n            if (primaryNode.Type == ClusterNodeType.Secondary)\n            {\n                //secondary node was promoted to primary node\n                ClusterNode formerPrimaryNode = GetPrimaryNode();\n\n                //dispose former primary node immediately to stop heartbeat\n                formerPrimaryNode.Dispose();\n\n                //remove former primary node from cluster nodes\n                IReadOnlyDictionary<int, ClusterNode> existingClusterNodes = _clusterNodes;\n                Dictionary<int, ClusterNode> updatedClusterNodes = new Dictionary<int, ClusterNode>(existingClusterNodes.Count - 1);\n\n                foreach (KeyValuePair<int, ClusterNode> existingClusterNode in existingClusterNodes)\n                {\n                    if (existingClusterNode.Key == formerPrimaryNode.Id)\n                        continue;\n","sourceCodeStart":1521,"sourceCodeEnd":1557,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L1521-L1557","documentation":"Thrown by UpdatePrimaryNodeAsync when the node selected by primaryNodeId resolves to the self node (primaryNode.State == ClusterNodeState.Self). UpdatePrimaryNodeAsync is meant to point at a *remote* primary; updating the self node's own address via this API is not permitted because it would rewrite the local node's identity from under itself.","triggerScenarios":"Passing a primaryNodeId that equals this server's own node Id, on a server that is currently the primary (so GetPrimaryNode() is Self).","commonSituations":"Operator selected their own node in a 'choose new primary' dropdown; automation passed the self node's Id by mistake; the cluster has only one node and the caller tried to 'update' it.","solutions":["Select a different, remote node Id (or pass -1 if you genuinely mean the current remote primary).","Filter the self node out of any 'pick primary' UI list before submission.","If you meant to change this server's own advertised URL, use the node's own UpdateNode path rather than UpdatePrimaryNodeAsync."],"exampleFix":"// before\nawait clusterManager.UpdatePrimaryNodeAsync(primaryUrl, primaryNodeId: pickedId);\n\n// after\nif (clusterManager.ClusterNodes[pickedId].State == ClusterNodeState.Self)\n    return BadRequest(\"Cannot target the self node via update-primary.\");\nawait clusterManager.UpdatePrimaryNodeAsync(primaryUrl, primaryNodeId: pickedId);","handlingStrategy":"validation","validationCode":"if (primaryNodeId >= 0 && clusterManager.ClusterNodes[primaryNodeId].State == ClusterNodeState.Self)\n    return BadRequest(\"Cannot target the self node via update-primary.\");\nawait clusterManager.UpdatePrimaryNodeAsync(primaryUrl, primaryNodeId: primaryNodeId);","typeGuard":"static bool IsSelfNodeId(ClusterManager cm, int id)\n    => id >= 0 && cm.ClusterNodes.TryGetValue(id, out var n) && n.State == ClusterNodeState.Self;","tryCatchPattern":"try { await clusterManager.UpdatePrimaryNodeAsync(primaryUrl, primaryNodeId: id); }\ncatch (DnsServerException ex) when (ex.Message.Contains(\"self node and cannot be updated\"))\n{ /* pick a remote node id instead */ }","preventionTips":["Exclude the self node from 'pick primary' selection lists.","Prefer -1 (current primary) unless you specifically need to target a remote node.","Validate the selected id is not the self node before submitting."],"tags":["cluster","role-guard","update-primary","self-node","technitium"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}