{"record":{"id":"29788368e045f904","repo":"TechnitiumSoftware/DnsServer","slug":"no-active-session-exist-to-logout","errorCode":null,"errorMessage":"No active session exist to logout.","messagePattern":"No active session exist to logout\\.","errorType":"exception","errorClass":"HttpApiClientException","httpStatus":null,"severity":"error","filePath":"DnsServerCore.HttpApi/HttpApiClient.cs","lineNumber":210,"sourceCode":"            using JsonDocument jsonDoc = await JsonDocument.ParseAsync(httpResponse.Content.ReadAsStream(cancellationToken), cancellationToken: cancellationToken);\n            JsonElement rootElement = jsonDoc.RootElement;\n\n            CheckResponseStatus(rootElement);\n\n            SessionInfo? sessionInfo = rootElement.Deserialize<SessionInfo>(_serializerOptions);\n            if (sessionInfo is null)\n                throw new HttpApiClientException(\"Invalid JSON response was received.\");\n\n            _httpClient.DefaultRequestHeaders.Add(\"Authorization\", \"Bearer \" + sessionInfo.Token);\n            _loggedIn = true;\n\n            return sessionInfo;\n        }\n\n        public async Task LogoutAsync(CancellationToken cancellationToken = default)\n        {\n            if (!_loggedIn)\n                throw new HttpApiClientException(\"No active session exist to logout.\");\n\n            Stream stream = await _httpClient.GetStreamAsync($\"api/user/logout\", cancellationToken);\n\n            using JsonDocument jsonDoc = await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken);\n            JsonElement rootElement = jsonDoc.RootElement;\n\n            CheckResponseStatus(rootElement);\n\n            _httpClient.DefaultRequestHeaders.Remove(\"Authorization\");\n            _loggedIn = false;\n        }\n\n        public void UseApiToken(string token)\n        {\n            if (_loggedIn)\n                throw new HttpApiClientException(\"Already logged in. Please create a new object to use a different API token.\");\n\n            _httpClient.DefaultRequestHeaders.Add(\"Authorization\", \"Bearer \" + token);","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore.HttpApi/HttpApiClient.cs#L192-L228","documentation":"LogoutAsync requires an active session. It checks _loggedIn and throws this HttpApiClientException if false, because there is no Authorization header to clear and no session to terminate server-side. The guard runs before any HTTP request is made.","triggerScenarios":"Calling LogoutAsync on a freshly constructed HttpApiClient, or after a previous LogoutAsync/failed login left _loggedIn false.","commonSituations":"Logout logic in a finally/dispose path that runs even when login never succeeded; calling logout twice; cleanup code that does not track session state.","solutions":["Guard LogoutAsync with a check of the logged-in state (or wrap in try/catch).","Only call logout after a confirmed successful login.","Track session state in your own code to avoid redundant logout calls."],"exampleFix":"// before\nawait client.LogoutAsync(); // throws if never logged in\n\n// after\nif (client.IsLoggedIn) // or track via your own bool\n    await client.LogoutAsync();","handlingStrategy":"validation","validationCode":"if (client.IsLoggedIn)\n    await client.LogoutAsync();","typeGuard":null,"tryCatchPattern":"catch (HttpApiClientException ex) when (ex.Message == \"No active session exist to logout.\")\n{\n    // benign: nothing to do, swallow or log at debug\n}","preventionTips":["Guard logout with an IsLoggedIn check.","Only call logout after a confirmed login.","Use try/catch in dispose/cleanup paths where login state is uncertain."],"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"}