{"record":{"id":"9ad1bd0658a54fef","repo":"mastra-ai/mastra","slug":"telegram-rejected-the-bot-token-cause-instanceo","errorCode":null,"errorMessage":"Telegram rejected the bot token: ${cause instanceof Error ? cause.message : String(cause)}","messagePattern":"Telegram rejected the bot token: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/telegram/src/telegram-client.ts","lineNumber":71,"sourceCode":"}\n\n/**\n * Validate a bot token via `getMe` and resolve the bot's identity. Throws if\n * the token is rejected or the returned user is not a bot.\n *\n * @see https://core.telegram.org/bots/api#getme\n */\nexport async function getMe(botToken: string, apiBaseUrl: string = TELEGRAM_API_BASE_URL): Promise<TelegramUser> {\n  let result: TelegramUser;\n  try {\n    result = await botApiRequest<TelegramUser>(botToken, 'getMe', apiBaseUrl);\n  } catch (cause) {\n    // A transport/timeout failure is a connectivity problem, not a token\n    // rejection — surface it as-is rather than mislabeling it as a bad token.\n    if (cause instanceof Error && (cause as { isTransportError?: boolean }).isTransportError) {\n      throw cause;\n    }\n    throw new Error(`Telegram rejected the bot token: ${cause instanceof Error ? cause.message : String(cause)}`, {\n      cause,\n    });\n  }\n  if (!result?.is_bot) {\n    throw new Error('Telegram getMe returned a non-bot user; expected a BotFather token');\n  }\n  return result;\n}\n\n/** Options for {@link setWebhook}. */\nexport interface SetWebhookOptions {\n  /** Public HTTPS URL Telegram will POST updates to. */\n  url: string;\n  /** Shared secret echoed back as `X-Telegram-Bot-Api-Secret-Token` on every POST. */\n  secretToken: string;\n  /** Update types to receive. Note: `message_reaction` must be listed explicitly. */\n  allowedUpdates?: string[];\n  /** Drop the backlog of updates queued while the bot was offline. */","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/channels/telegram/src/telegram-client.ts#L53-L89","documentation":"getMe() validates a bot token via Telegram's getMe endpoint and is the canonical 'is this token good?' check. If botApiRequest throws a non-transport error (i.e. Telegram rejected the request — usually HTTP 401 Unauthorized for a bad token), it is rethrown wrapped as 'Telegram rejected the bot token: <cause>'. Genuine transport failures (timeouts) are rethrown as-is to avoid mislabeling connectivity problems as bad tokens, and a non-bot user result has its own distinct error.","triggerScenarios":"Calling getMe()/me() — or any flow that validates a bot token (bot registration, install verification) — with an invalid, revoked, or mistyped BotFather token, causing getMe to fail with 401 Unauthorized.","commonSituations":"Typo when pasting the token from BotFather; token regenerated/revoked but the old value still in env/DB; using a user token (xoxp-like or a personal token) instead of a bot token; trailing whitespace/newline in the token env var.","solutions":["Regenerate a token via @BotFather (/mybots > API Token) and update the stored/env value.","Trim whitespace and verify the token format matches the BotFather-issued pattern (digits:alphanumeric).","Confirm the value is a bot token from BotFather, not a user or app token.","If the cause message is a timeout/network error (transport), fix connectivity — the wrapper preserves genuine transport errors unwrapped."],"exampleFix":"// before\nconst client = createTelegramClient(process.env.TELEGRAM_BOT_TOKEN);\n// after\nconst token = process.env.TELEGRAM_BOT_TOKEN?.trim();\nif (!token || !/^\\d+:[\\w-]{30,}$/.test(token)) {\n  throw new Error('TELEGRAM_BOT_TOKEN is not a valid BotFather token');\n}\nconst client = createTelegramClient(token);","handlingStrategy":"validation","validationCode":"const token = process.env.TELEGRAM_BOT_TOKEN?.trim();\nif (!token || !/^\\d+:[\\w-]{30,}$/.test(token)) {\n  throw new Error('TELEGRAM_BOT_TOKEN missing or malformed (expected BotFather format)');\n}\nawait getMe(token); // confirms validity with Telegram before use","typeGuard":null,"tryCatchPattern":"try {\n  await getMe(token);\n} catch (e) {\n  const m = /Telegram rejected the bot token: (.+)/.exec(e.message);\n  if (m) {\n    console.error(`Bad bot token (${m[1]}); regenerate via @BotFather`);\n  } else throw e; // transport errors surface as-is\n}","preventionTips":["Trim tokens read from env/files — stray newlines cause 401s.","Only use BotFather-issued bot tokens; keep a startup getMe health check.","Update stored tokens everywhere immediately after regenerating via BotFather."],"tags":["telegram","authentication","bot-token"],"backgroundTag":"invalid-bot-token","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}