TechnitiumSoftware/DnsServer · error · HttpApiClientException

Already logged in. Please create a new object to use a diffe

Error message

Already logged in. Please create a new object to use a different API token.

What it means

UseApiToken sets up token-based auth and refuses to run if the client already holds a session (_loggedIn == true), because swapping the Authorization header mid-session would corrupt state. The message explicitly directs the caller to instantiate a new HttpApiClient for a different token. Fires before any HTTP traffic.

Source

Thrown at DnsServerCore.HttpApi/HttpApiClient.cs:226

        {
            if (!_loggedIn)
                throw new HttpApiClientException("No active session exist to logout.");

            Stream stream = await _httpClient.GetStreamAsync($"api/user/logout", cancellationToken);

            using JsonDocument jsonDoc = await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken);
            JsonElement rootElement = jsonDoc.RootElement;

            CheckResponseStatus(rootElement);

            _httpClient.DefaultRequestHeaders.Remove("Authorization");
            _loggedIn = false;
        }

        public void UseApiToken(string token)
        {
            if (_loggedIn)
                throw new HttpApiClientException("Already logged in. Please create a new object to use a different API token.");

            _httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
            _loggedIn = true;
        }

        public async Task<DashboardStats> GetDashboardStatsAsync(string actingUsername, DashboardStatsType type = DashboardStatsType.LastHour, bool utcFormat = false, string acceptLanguage = "en-US,en;q=0.5", bool dontTrimQueryTypeData = false, DateTime startDate = default, DateTime endDate = default, CancellationToken cancellationToken = default)
        {
            if (!_loggedIn)
                throw new HttpApiClientException("No active session exists. Please login and try again.");

            string path = $"api/dashboard/stats/get?actingUser={Uri.EscapeDataString(actingUsername)}&type={type}&utc={utcFormat}&dontTrimQueryTypeData={dontTrimQueryTypeData}";

            if (type == DashboardStatsType.Custom)
                path += $"&start={startDate:O}&end={endDate:O}";

            HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, new Uri(_serverUrl, path));
            httpRequest.Headers.Add("Accept-Language", acceptLanguage);

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Construct a new HttpApiClient instance for each distinct API token.
  2. Call LogoutAsync first if you must reuse the instance (then UseApiToken).
  3. Prefer a factory method that hands out fresh authenticated clients per token.

Example fix

// before
client.UseApiToken(tokenA);
client.UseApiToken(tokenB); // throws

// after
var clientB = new HttpApiClient(serverUrl);
clientB.UseApiToken(tokenB);
Defensive patterns

Strategy: validation

Validate before calling

if (client.IsLoggedIn)
    throw new InvalidOperationException(
        "Client already authenticated. Create a new HttpApiClient for a different token.");

client.UseApiToken(token);

Prevention

When it happens

Trigger: Calling UseApiToken after LoginAsync or after a prior UseApiToken on the same instance without resetting it.

Common situations: Reusing one HttpApiClient for multiple tokens/accounts; calling UseApiToken inside a loop that processes several tokens.

Related errors


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