{"record":{"id":"4871960f9e8f4377","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-update-cluster-options-only-the-primary","errorCode":null,"errorMessage":"Failed to update Cluster options: only the Primary node can update the Cluster options.","messagePattern":"Failed to update Cluster options: only the Primary node can update the Cluster options\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":905,"sourceCode":"                                                    allowedZones: true,\n                                                    blockedZones: true,\n                                                    blockLists: true,\n                                                    apps: true,\n                                                    scopes: false,\n                                                    stats: false,\n                                                    logs: false,\n                                                    isConfigTransfer: true,\n                                                    ifModifiedSince: ifModifiedSince,\n                                                    includeZones: includeZones);\n        }\n\n        public void UpdateClusterOptions(ushort heartbeatRefreshIntervalSeconds, ushort heartbeatRetryIntervalSeconds, ushort configRefreshIntervalSeconds, ushort configRetryIntervalSeconds)\n        {\n            if (!ClusterInitialized)\n                throw new DnsServerException(\"Failed to update Cluster options: the Cluster is not initialized.\");\n\n            if (GetSelfNode().Type != ClusterNodeType.Primary)\n                throw new DnsServerException(\"Failed to update Cluster options: only the Primary node can update the Cluster options.\");\n\n            if ((heartbeatRefreshIntervalSeconds < 10) || (heartbeatRefreshIntervalSeconds > 300))\n                throw new ArgumentOutOfRangeException(nameof(heartbeatRefreshIntervalSeconds));\n\n            if ((heartbeatRetryIntervalSeconds < 10) || (heartbeatRetryIntervalSeconds > 300))\n                throw new ArgumentOutOfRangeException(nameof(heartbeatRetryIntervalSeconds));\n\n            if ((configRefreshIntervalSeconds < 30) || (configRefreshIntervalSeconds > 3600))\n                throw new ArgumentOutOfRangeException(nameof(configRefreshIntervalSeconds));\n\n            if ((configRetryIntervalSeconds < 30) || (configRetryIntervalSeconds > 3600))\n                throw new ArgumentOutOfRangeException(nameof(configRetryIntervalSeconds));\n\n            if (configRefreshIntervalSeconds <= heartbeatRefreshIntervalSeconds)\n                throw new ArgumentException(\"Failed to update Cluster options: The config refresh interval must be greater than the heartbeat refresh interval.\");\n\n            bool changed = false;\n","sourceCodeStart":887,"sourceCodeEnd":923,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L887-L923","documentation":"UpdateClusterOptions may only be called on the cluster Primary (GetSelfNode().Type == Primary). Cluster options are Primary-owned and replicated to Secondaries.","triggerScenarios":"Calling the tuning endpoint on a Secondary; an LB routing to a non-Primary member; a demotion after the client cached the role.","commonSituations":"Failover flipping the Primary; client hitting a member by IP; multi-node deployments without role-aware routing.","solutions":["Send option updates to the current Primary","Rediscover the Primary after failover","Use role-aware routing in front of the API"],"exampleFix":"// before\nclusterManager.UpdateClusterOptions(hb, hbRetry, cfg, cfgRetry);\n\n// after\nif (clusterManager.GetSelfNode().Type != ClusterNodeType.Primary)\n    return Redirect(\"Update options on the Primary node.\");\nclusterManager.UpdateClusterOptions(hb, hbRetry, cfg, cfgRetry);","handlingStrategy":"validation","validationCode":"if (clusterManager.GetSelfNode().Type != ClusterNodeType.Primary)\n    return BadRequest(\"Only the Primary can update cluster options.\");\nclusterManager.UpdateClusterOptions(hb, hbRetry, cfg, cfgRetry);","typeGuard":null,"tryCatchPattern":"catch (DnsServerException ex) when (ex.Message.Contains(\"only the Primary node can update the Cluster options\"))\n{ /* rediscover Primary and retry */ }","preventionTips":["Route option changes through the Primary role, not a fixed member","Re-check the Primary after failover"],"tags":["cluster","primary-node","configuration","authorization","dns-server"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}