Tyrrrz/DiscordChatExporter · critical · DiscordChatExporterException

Authentication token is invalid.

Error message

Authentication token is invalid.

What it means

Thrown as DiscordChatExporterException(isFatal=true) inside ResolveTokenKindAsync after probing both `users/@me` as a user token AND as a bot token and receiving HttpStatusCode.Unauthorized for both. Because neither authentication path succeeded, the token is definitively invalid. The isFatal flag tells the CLI runner this is not a transient/per-channel issue.

Source

Thrown at DiscordChatExporter.Core/Discord/DiscordClient.cs:121

            "users/@me",
            TokenKind.User,
            cancellationToken
        );

        if (userResponse.StatusCode != HttpStatusCode.Unauthorized)
            return (_resolvedTokenKind = TokenKind.User).Value;

        // Try authenticating as a bot
        using var botResponse = await GetResponseAsync(
            "users/@me",
            TokenKind.Bot,
            cancellationToken
        );

        if (botResponse.StatusCode != HttpStatusCode.Unauthorized)
            return (_resolvedTokenKind = TokenKind.Bot).Value;

        throw new DiscordChatExporterException("Authentication token is invalid.", true);
    }

    private async ValueTask<HttpResponseMessage> GetResponseAsync(
        string url,
        CancellationToken cancellationToken = default
    ) =>
        await GetResponseAsync(
            url,
            await ResolveTokenKindAsync(cancellationToken),
            cancellationToken
        );

    private async ValueTask<JsonElement> GetJsonResponseAsync(
        string url,
        CancellationToken cancellationToken = default
    )
    {
        using var response = await GetResponseAsync(url, cancellationToken);

View on GitHub (pinned to f6865c8216)

Solutions

  1. Re-issue the token: regenerate a bot token in the Discord Developer Portal, or capture a fresh user token from the client.
  2. Pass the token explicitly with -t to rule out env-var corruption: `-t "<exact token>"`.
  3. Trim surrounding whitespace/quotes from the token before passing it.
  4. Confirm the token kind matches intent (bot token for self-bots is unsupported; user tokens are against Discord ToS and may be invalidated).

Example fix

// before
exportchat -c <id> -t "$DISCORD_TOKEN"  # env had a stale token
// after
exportchat -c <id> -t "<freshly copied token>"
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(token) || token.Trim().Length < 10)
    throw new InvalidOperationException("Token appears missing or malformed.");
// optional: probe before the batch
var probe = await discord.TryGetUserAsync(currentUser, ct);
if (probe is null) throw new InvalidOperationException("Token rejected by Discord.");

Try / catch

try { await discord.GetGuildAsync(guildId, ct); }
catch (DiscordChatExporterException ex) when (ex.IsFatal && ex.Message.Contains("invalid"))
{
    logger.LogError("Token invalid or expired — refresh and retry");
    throw;
}

Prevention

When it happens

Trigger: ResolveTokenKindAsync is called (triggered by any API call). The user-token probe at users/@me returned non-401 so it tried bot; the bot probe at DiscordClient.cs:121 also returned 401; both failed so the exception is raised.

Common situations: Token typo or truncation; token copied with stray whitespace/quotes; token revoked by Discord (password change, logout, bot reset); using a bot token in a user-token field or vice-versa; environment variable DISCORD_TOKEN unset/empty resolving to garbage.

Understand the failure class

Related errors


AI-assisted analysis of Tyrrrz/DiscordChatExporter@f6865c8216 (2026-08-13). Data as JSON: /api/errors/66e687ce48721ce1. Report an issue: GitHub.