mastra-ai/mastra · error

Telegram getMe returned a non-bot user; expected a BotFather

Error message

Telegram getMe returned a non-bot user; expected a BotFather token

What it means

After calling Telegram's getMe API with the supplied bot token, the response user object did not have is_bot set to true. The TelegramProvider requires a token created via BotFather; a valid-looking token that resolves to a normal user account cannot act as a bot. The library throws to fail fast before registering webhooks or polling.

Source

Thrown at channels/telegram/src/telegram-client.ts:76

 *
 * @see https://core.telegram.org/bots/api#getme
 */
export async function getMe(botToken: string, apiBaseUrl: string = TELEGRAM_API_BASE_URL): Promise<TelegramUser> {
  let result: TelegramUser;
  try {
    result = await botApiRequest<TelegramUser>(botToken, 'getMe', apiBaseUrl);
  } catch (cause) {
    // A transport/timeout failure is a connectivity problem, not a token
    // rejection — surface it as-is rather than mislabeling it as a bad token.
    if (cause instanceof Error && (cause as { isTransportError?: boolean }).isTransportError) {
      throw cause;
    }
    throw new Error(`Telegram rejected the bot token: ${cause instanceof Error ? cause.message : String(cause)}`, {
      cause,
    });
  }
  if (!result?.is_bot) {
    throw new Error('Telegram getMe returned a non-bot user; expected a BotFather token');
  }
  return result;
}

/** Options for {@link setWebhook}. */
export interface SetWebhookOptions {
  /** Public HTTPS URL Telegram will POST updates to. */
  url: string;
  /** Shared secret echoed back as `X-Telegram-Bot-Api-Secret-Token` on every POST. */
  secretToken: string;
  /** Update types to receive. Note: `message_reaction` must be listed explicitly. */
  allowedUpdates?: string[];
  /** Drop the backlog of updates queued while the bot was offline. */
  dropPendingUpdates?: boolean;
}

/**
 * Register a per-bot webhook. Setting a webhook disables `getUpdates`

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Create a bot with @BotFather via /newbot and use the issued token (it ends in a bot username and getMe returns is_bot: true)
  2. Verify the token with a manual GET https://api.telegram.org/bot<token>/getMe and confirm the response contains "is_bot": true
  3. Check for whitespace, quotes, or truncation in the env var holding the token (e.g. process.env.TELEGRAM_BOT_TOKEN)
  4. Regenerate the token via BotFather /revoke if the old one was rotated or invalid

Example fix

// before
new TelegramProvider({ botToken: process.env.TELEGRAM_USER_TOKEN })
// after
new TelegramProvider({ botToken: process.env.TELEGRAM_BOT_TOKEN }) // token from @BotFather
Defensive patterns

Strategy: validation

Validate before calling

async function assertBotToken(token: string, baseUrl = 'https://api.telegram.org') {
  const res = await fetch(`${baseUrl}/bot${token}/getMe`);
  const data: { ok: boolean; result?: { is_bot?: boolean } } = await res.json();
  if (!data.ok || !data.result?.is_bot) throw new Error('Token is not a BotFather bot token');
}

Type guard

function isBotUser(u: unknown): u is { id: number; is_bot: true; username: string } {
  return typeof u === 'object' && u !== null && (u as any).is_bot === true;
}

Try / catch

try {
  await provider.connect(agentId, { botToken });
} catch (err) {
  if (err instanceof Error && err.message.includes('non-bot user')) {
    throw new Error('TELEGRAM_BOT_TOKEN is not a BotFather token — regenerate via @BotFather');
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling TelegramProvider.connect() with a botToken that is actually a non-bot user token, or a corrupted/placeholder token that Telegram nevertheless authenticates but returns a user with is_bot=false.

Common situations: Pasting a user auth token instead of a BotFather token; token copied from the wrong bot or truncated/reformatted so Telegram resolves it incorrectly; testing with dummy tokens like '123:ABC' in dev.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/0a253e0e79226c54. Report an issue: GitHub.