paperclipai/paperclip · error · Error

Discord token does not identify a bot user

Error message

Discord token does not identify a bot user

What it means

verifyDiscordBot fetches the authenticated user, application, and guild for a supplied bot token, then sanity-checks the identity. This error means the /users/@me payload did not look like a bot account: user.bot was falsy or id/username were missing — i.e. the token is valid but does not belong to a bot user, or the response was unexpectedly shaped.

Source

Thrown at server/src/services/chat-discord.ts:230

      input.botToken,
      "/users/@me",
      "bot identity lookup",
    ),
    discordJson<DiscordApplication>(
      input.fetch,
      input.botToken,
      "/oauth2/applications/@me",
      "application lookup",
    ),
    discordJson<DiscordGuild>(
      input.fetch,
      input.botToken,
      `/guilds/${encodeURIComponent(guildId)}`,
      "server membership lookup",
    ),
  ]);
  if (!user.bot || !user.id || !user.username) {
    throw new Error("Discord token does not identify a bot user");
  }
  if (application.id !== applicationId || user.id !== applicationId) {
    throw new Error(
      "Discord Application ID does not match the supplied bot token",
    );
  }
  if (((application.flags ?? 0) & MESSAGE_CONTENT_FLAGS) === 0) {
    throw new Error(
      "Discord Message Content intent is not enabled for this application",
    );
  }
  if (guild.id !== guildId) {
    throw new Error("Discord bot is not installed in the selected server");
  }
  return {
    providerAccountId: guildId,
    providerAccountLabel: guild.name ?? guildId,
    botExternalId: user.id,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Create/copy the token from the Discord Developer Portal under your Application's Bot page (token starting roughly with 'Bot ' semantics) and never a user token or client secret
  2. Call GET /users/@me manually with the token and confirm the JSON contains "bot": true plus id and username
  3. Regenerate the bot token if it was reset and update the configured value

Example fix

// before
DISCORD_BOT_TOKEN=mFa.abc123.clientsecret
// after
DISCORD_BOT_TOKEN=MTIzNDU2Nzg5MDEyMzQ1Njc4.GaBcDe.xxxxxxxxxxxxxxxxxxxxxxx
Defensive patterns

Strategy: validation

Validate before calling

// Probe before verifyDiscordBot
const res = await fetch("https://discord.com/api/v10/users/@me", {
  headers: { authorization: `Bot ${token}` },
});
const user = await res.json();
if (!res.ok || user.bot !== true || !user.id || !user.username) {
  throw new Error("Token is not a valid bot token");
}

Type guard

const isBotUser = (u) => !!u && typeof u === "object" && u.bot === true && typeof u.id === "string" && u.id.length > 0 && typeof u.username === "string" && u.username.length > 0;

Try / catch

try {
  await verifyDiscordBot(input);
} catch (err) {
  if (err.message === "Discord token does not identify a bot user") {
    throw new ConfigError("botToken must be a bot token from the Developer Portal, not a user token or client secret");
  }
  throw err;
}

Prevention

When it happens

Trigger: Using a user account token (not a bot token) as input.botToken; a token that authenticates but returns a user object with bot=false or missing id/username; a Discord API change or proxy stripping fields from the response.

Common situations: Configuring a personal Discord account token instead of a token created under Developer Portal > Bot; copying an OAuth client secret instead of the bot token; partially blocked/undocumented API responses.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/de9ea3f91603f8a3. Report an issue: GitHub.