TechnitiumSoftware/DnsServer · error · HttpApiClientException

Already logged in.

Error message

Already logged in.

What it means

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.

Source

Thrown at DnsServerCore.HttpApi/HttpApiClient.cs:172

                        if (rootElement.TryGetProperty("errorMessage", out JsonElement jsonErrorMessage))
                            throw new TwoFactorAuthRequiredHttpApiClientException(jsonErrorMessage.GetString()!);

                        throw new TwoFactorAuthRequiredHttpApiClientException();
                    }

                default:
                    throw new HttpApiClientException("Unknown status value was received: " + status);
            }
        }

        #endregion

        #region public

        public async Task<SessionInfo> LoginAsync(string username, string password, string? totp = null, bool includeInfo = false, CancellationToken cancellationToken = default)
        {
            if (_loggedIn)
                throw new HttpApiClientException("Already logged in.");

            HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, new Uri(_serverUrl, $"api/user/login"));

            Dictionary<string, string> parameters = new Dictionary<string, string>
            {
                { "user", username },
                { "pass", password },
                { "includeInfo", includeInfo.ToString() }
            };

            if (totp is not null)
                parameters.Add("totp", totp);

            httpRequest.Content = new FormUrlEncodedContent(parameters);

            HttpResponseMessage httpResponse = await _httpClient.SendAsync(httpRequest, cancellationToken);

            httpResponse.EnsureSuccessStatusCode();

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Call LogoutAsync (or create a fresh HttpApiClient instance) before logging in again.
  2. If using an API token, call UseApiToken once instead of LoginAsync.
  3. Structure your code so each HttpApiClient owns exactly one session lifecycle.

Example fix

// before
await client.LoginAsync(user, pass);
// ... later, mistakenly:
await client.LoginAsync(user, pass); // throws

// after
await client.LogoutAsync();
await client.LoginAsync(user, pass);
Defensive patterns

Strategy: validation

Validate before calling

if (client.IsLoggedIn) // or track via your own bool mirroring _loggedIn
    throw new InvalidOperationException("Already logged in; logout or use a new instance.");

await client.LoginAsync(user, pass);

Try / catch

catch (HttpApiClientException ex) when (ex.Message == "Already logged in.")
{
    // either ignore (already authed) or logout first
}

Prevention

When it happens

Trigger: Calling LoginAsync a second time on the same HttpApiClient instance without an intervening LogoutAsync, or after UseApiToken already set _loggedIn.

Common situations: Reusing a shared/singleton HttpApiClient across requests and calling Login on each one; calling Login then later calling Login again forgetting to logout.

Related errors


AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13). Data as JSON: /api/errors/8f985e42fa9fa7b6. Report an issue: GitHub.