{"record":{"id":"0a2b375f52135aec","repo":"TechnitiumSoftware/DnsServer","slug":"no-api-token-was-found-for-the-cluster-domain","errorCode":null,"errorMessage":"No API token was found for the Cluster domain.","messagePattern":"No API token was found for the Cluster domain\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Cluster/ClusterNode.cs","lineNumber":210,"sourceCode":"                throw new InvalidOperationException();\n\n            if (_apiClient is null)\n            {\n                HttpApiClient apiClient = new HttpApiClient(_url, _clusterManager.DnsWebService.DnsServer.Proxy, _clusterManager.DnsWebService.DnsServer.IPv6Mode, false, new InternalDnsClient(_clusterManager.DnsWebService.DnsServer, this));\n\n                UserSession clusterApiToken = null;\n\n                foreach (UserSession session in _clusterManager.DnsWebService.AuthManager.Sessions)\n                {\n                    if (session.Type == UserSessionType.ClusterApiToken)\n                    {\n                        clusterApiToken = session;\n                        break;\n                    }\n                }\n\n                if (clusterApiToken is null)\n                    throw new InvalidOperationException(\"No API token was found for the Cluster domain.\");\n\n                apiClient.UseApiToken(clusterApiToken.Token);\n\n                _apiClient = apiClient;\n            }\n\n            return _apiClient;\n        }\n\n        private async void HeartbeatTimerCallbackAsync(object state)\n        {\n            bool success = true;\n\n            try\n            {\n                ClusterInfo clusterInfo = await GetClusterStateAsync();\n\n                if (_type == ClusterNodeType.Primary)","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterNode.cs#L192-L228","documentation":"Thrown by ClusterNode.GetApiClient() (InvalidOperationException) when no UserSession of type UserSessionType.ClusterApiToken exists in AuthManager.Sessions. The cluster API token is the credential a node uses to authenticate inter-node REST calls; without it the HttpApiClient cannot be created. The token is normally provisioned by ClusterManager during init (it auto-upgrades an admin API token named after the cluster domain) — this error means that provisioning failed or the token was deleted.","triggerScenarios":"Any inter-node API call (GetClusterStateAsync, SyncConfigAsync, ProxyRequest, dashboard stats, etc.) on a non-self node that triggers GetApiClient() when the cluster API token session is missing from AuthManager.","commonSituations":"The admin user that owned the cluster API token was deleted; the token was revoked via the auth API; a config migration/import skipped the token upgrade step; cluster was enabled but the matching admin API token (named = cluster domain) never existed to be upgraded.","solutions":["Re-create the cluster API token: in the web UI create an admin API token named after the cluster domain, then restart / re-init the cluster so it is upgraded to a ClusterApiToken.","Verify the owning user still exists and is a member of the Administrators group.","Restart the DNS server service so ClusterManager's startup token-repair logic (ClusterManager.cs:124-148) re-runs.","Check AuthManager.Sessions at runtime to confirm whether a ClusterApiToken session is present before issuing inter-node calls."],"exampleFix":"// before: cluster enabled but token was deleted -> any inter-node call throws [204]\nawait node.GetClusterStateAsync(); // InvalidOperationException\n\n// after: re-provision the token (admin API token named = cluster domain), then restart\nauthManager.CreateSession(UserSessionType.ApiToken, clusterDomain, adminUsername, remoteAddress, userAgent);\n// restart service; on init ClusterManager upgrades it to ClusterApiToken\nawait node.GetClusterStateAsync(); // ok","handlingStrategy":"validation","validationCode":"// Before any inter-node API call, confirm the cluster API token session exists\nbool hasToken = _clusterManager.DnsWebService.AuthManager.Sessions\n    .Any(s => s.Type == UserSessionType.ClusterApiToken);\n\nif (!hasToken)\n    throw new InvalidOperationException(\"Cluster API token missing; re-provision it before cluster operations.\");","typeGuard":null,"tryCatchPattern":"try\n{\n    await node.GetClusterStateAsync(cancellationToken);\n}\ncatch (InvalidOperationException ex) when (ex.Message == \"No API token was found for the Cluster domain.\")\n{\n    // trigger token re-provisioning / alert admin, then retry once\n    logger.LogError(\"Cluster API token missing for node {Node}.\", node);\n    throw;\n}","preventionTips":["Keep the cluster API token's owning admin user active and in the Administrators group.","Do not revoke the API token named after the cluster domain.","Restart the service after restoring configs so the startup token-repair logic re-runs."],"tags":["cluster","auth","api-token","configuration","invalid-operation"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}