{"record":{"id":"8f985e42fa9fa7b6","repo":"TechnitiumSoftware/DnsServer","slug":"already-logged-in","errorCode":null,"errorMessage":"Already logged in.","messagePattern":"Already logged in\\.","errorType":"exception","errorClass":"HttpApiClientException","httpStatus":null,"severity":"error","filePath":"DnsServerCore.HttpApi/HttpApiClient.cs","lineNumber":172,"sourceCode":"                        if (rootElement.TryGetProperty(\"errorMessage\", out JsonElement jsonErrorMessage))\n                            throw new TwoFactorAuthRequiredHttpApiClientException(jsonErrorMessage.GetString()!);\n\n                        throw new TwoFactorAuthRequiredHttpApiClientException();\n                    }\n\n                default:\n                    throw new HttpApiClientException(\"Unknown status value was received: \" + status);\n            }\n        }\n\n        #endregion\n\n        #region public\n\n        public async Task<SessionInfo> LoginAsync(string username, string password, string? totp = null, bool includeInfo = false, CancellationToken cancellationToken = default)\n        {\n            if (_loggedIn)\n                throw new HttpApiClientException(\"Already logged in.\");\n\n            HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, new Uri(_serverUrl, $\"api/user/login\"));\n\n            Dictionary<string, string> parameters = new Dictionary<string, string>\n            {\n                { \"user\", username },\n                { \"pass\", password },\n                { \"includeInfo\", includeInfo.ToString() }\n            };\n\n            if (totp is not null)\n                parameters.Add(\"totp\", totp);\n\n            httpRequest.Content = new FormUrlEncodedContent(parameters);\n\n            HttpResponseMessage httpResponse = await _httpClient.SendAsync(httpRequest, cancellationToken);\n\n            httpResponse.EnsureSuccessStatusCode();","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore.HttpApi/HttpApiClient.cs#L154-L190","documentation":"LoginAsync refuses to run when _loggedIn is already true. The client tracks a single session per HttpApiClient instance and prevents overlapping logins that would orphan the prior Authorization header. This fires at the very start of LoginAsync before any HTTP call.","triggerScenarios":"Calling LoginAsync a second time on the same HttpApiClient instance without an intervening LogoutAsync, or after UseApiToken already set _loggedIn.","commonSituations":"Reusing a shared/singleton HttpApiClient across requests and calling Login on each one; calling Login then later calling Login again forgetting to logout.","solutions":["Call LogoutAsync (or create a fresh HttpApiClient instance) before logging in again.","If using an API token, call UseApiToken once instead of LoginAsync.","Structure your code so each HttpApiClient owns exactly one session lifecycle."],"exampleFix":"// before\nawait client.LoginAsync(user, pass);\n// ... later, mistakenly:\nawait client.LoginAsync(user, pass); // throws\n\n// after\nawait client.LogoutAsync();\nawait client.LoginAsync(user, pass);","handlingStrategy":"validation","validationCode":"if (client.IsLoggedIn) // or track via your own bool mirroring _loggedIn\n    throw new InvalidOperationException(\"Already logged in; logout or use a new instance.\");\n\nawait client.LoginAsync(user, pass);","typeGuard":null,"tryCatchPattern":"catch (HttpApiClientException ex) when (ex.Message == \"Already logged in.\")\n{\n    // either ignore (already authed) or logout first\n}","preventionTips":["Model one session per HttpApiClient instance.","Track login state in your own code to avoid double-login.","Prefer UseApiToken for long-running automation over repeated LoginAsync."],"tags":["http-api","client","session","state"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}