{"record":{"id":"ab11b42dfbe0a3e0","repo":"TechnitiumSoftware/DnsServer","slug":"failed-to-refresh-configuration-only-secondary-no","errorCode":null,"errorMessage":"Failed to refresh configuration: only Secondary nodes can sync configuration from Primary nodes.","messagePattern":"Failed to refresh configuration: only Secondary nodes can sync configuration from Primary nodes\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"warning","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":1613,"sourceCode":"            _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(clusterSecondaryCatalogZoneInfo.Name);\n            SaveConfigFile();\n\n            //trigger config and zone refresh\n            TriggerRefreshForConfig(CONFIG_REFRESH_TIMER_INTERVAL);\n\n            return primaryNode;\n        }\n\n        public void TriggerRefreshForConfig(IReadOnlyCollection<string> configRefreshIncludeZones = null)\n        {\n            //do validation\n            if (!ClusterInitialized)\n                throw new DnsServerException(\"Failed to refresh configuration: the Cluster is not initialized.\");\n\n            ClusterNode primaryNode = GetPrimaryNode();\n\n            if (primaryNode.State == ClusterNodeState.Self)\n                throw new DnsServerException(\"Failed to refresh configuration: only Secondary nodes can sync configuration from Primary nodes.\");\n\n            TriggerRefreshForConfig(CONFIG_REFRESH_TIMER_INTERVAL, configRefreshIncludeZones);\n        }\n\n        public void TriggerResyncForConfig()\n        {\n            //do validation\n            if (!ClusterInitialized)\n                throw new DnsServerException(\"Failed to resync configuration: the Cluster is not initialized.\");\n\n            ClusterNode primaryNode = GetPrimaryNode();\n\n            if (primaryNode.State == ClusterNodeState.Self)\n                throw new DnsServerException(\"Failed to resync configuration: only Secondary nodes can sync configuration from Primary nodes.\");\n\n            _configLastSynced = DateTime.UnixEpoch; //to ensure complete config resync\n\n            //trigger immediate config refresh","sourceCodeStart":1595,"sourceCodeEnd":1631,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L1595-L1631","documentation":"Thrown by the public TriggerRefreshForConfig when GetPrimaryNode().State == ClusterNodeState.Self — i.e. this server is itself the primary. Secondary-to-primary config sync is the whole point of refresh, so a primary node has no upstream to pull from. The guard prevents a primary from trying to sync config from itself.","triggerScenarios":"Calling TriggerRefreshForConfig on the primary node of the cluster (GetPrimaryNode() is Self).","commonSituations":"The same admin console is used for primary and secondary nodes and the refresh button was clicked while logged into the primary; automation runs a periodic 'refresh config' job on every cluster member without checking role.","solutions":["Only call TriggerRefreshForConfig from Secondary nodes; on the primary it is a no-op by definition.","In shared jobs, branch on whether GetPrimaryNode().State == Self and skip refresh there.","Hide/disable the refresh action when the current node is the primary."],"exampleFix":"// before\nclusterManager.TriggerRefreshForConfig(includeZones);\n\n// after\nif (clusterManager.GetPrimaryNode().State == ClusterNodeState.Self)\n    return Ok(\"Primary node; nothing to refresh.\"); // no-op\nclusterManager.TriggerRefreshForConfig(includeZones);","handlingStrategy":"validation","validationCode":"if (clusterManager.GetPrimaryNode().State == ClusterNodeState.Self)\n    return Ok(\"Primary node; nothing to refresh.\");\nclusterManager.TriggerRefreshForConfig(includeZones);","typeGuard":"static bool IsSecondaryOfRemotePrimary(ClusterManager cm)\n    => cm.ClusterInitialized && cm.GetPrimaryNode().State != ClusterNodeState.Self;","tryCatchPattern":"try { clusterManager.TriggerRefreshForConfig(includeZones); }\ncatch (DnsServerException ex) when (ex.Message.Contains(\"only Secondary nodes can sync\"))\n{ /* running on primary; refresh is a no-op */ }","preventionTips":["Only invoke refresh from secondary nodes.","In shared jobs, skip refresh when GetPrimaryNode().State == Self.","Disable the refresh action in the UI when viewing the primary node."],"tags":["cluster","role-guard","config-refresh","primary-node","technitium"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}