{"record":{"id":"4464adac05d4ba93","repo":"Mintplex-Labs/anything-llm","slug":"invalid-bot-token-verification-error","errorCode":null,"errorMessage":"Invalid bot token: ${verification.error}","messagePattern":"Invalid bot token: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"server/endpoints/telegram.js","lineNumber":93,"sourceCode":"  app.post(\n    \"/telegram/connect\",\n    [validatedRequest, isSingleUserMode],\n    async (request, response) => {\n      try {\n        const { bot_token, default_workspace = null } = reqBody(request);\n        if (!bot_token) {\n          return response.status(400).json({\n            success: false,\n            error: \"Bot token is required.\",\n          });\n        }\n\n        // Verify the token with Telegram API\n        const verification = await TelegramBotService.verifyToken(\n          String(bot_token)\n        );\n        if (!verification.valid) {\n          return response.status(400).json({\n            success: false,\n            error: `Invalid bot token: ${verification.error}`,\n          });\n        }\n\n        let workspaceSlug = null;\n        if (default_workspace) workspaceSlug = String(default_workspace);\n        else {\n          const workspaces = await Workspace.where({}, 1);\n          if (workspaces.length) workspaceSlug = workspaces[0].slug;\n          else {\n            const { workspace } = await Workspace.new(\n              `${verification.username} Workspace`,\n              null,\n              { chatMode: \"automatic\" }\n            );\n            if (workspace) workspaceSlug = workspace.slug;\n          }","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/endpoints/telegram.js#L75-L111","documentation":"Returned by POST /telegram/connect when TelegramBotService.verifyToken() rejects the supplied bot token. verifyToken() builds a node-telegram-bot-api client and calls getMe(); Telegram's API answers 401 Unauthorized (or 404 Not Found) for wrong, revoked, or malformed tokens, and that library error is interpolated into this 400 response. A network-level failure to reach api.telegram.org also lands here, because any getMe() rejection marks the token invalid.","triggerScenarios":"POST /telegram/connect with a bot_token that is truthy but not a valid active token: token pasted with surrounding quotes, spaces, or a trailing newline; a token revoked via @BotFather /revoke after it was copied; a token for a different bot; or the server cannot open HTTPS to api.telegram.org (proxy/firewall/DNS) so getMe() rejects with ETIMEDOUT/ECONNREFUSED instead of an auth answer.","commonSituations":"Copy-paste from BotFather including quotes or a newline; regenerating the token and pasting the stale one; corporate egress proxy blocking telegram API; typo in the hash portion; running the connect endpoint from a network where Telegram is blocked.","solutions":["Re-copy the token from @BotFather exactly (format <numeric bot id>:<hash>), stripping any whitespace or quotes, and retry the connect request.","If unsure whether the token is still valid, send /revoke in @BotFather and use the freshly issued token.","Validate the token out-of-band: curl https://api.telegram.org/bot<TOKEN>/getMe must return {\"ok\":true,...}; a 401 confirms the token itself is bad.","If getMe fails with a network error (ETIMEDOUT, ENOTFOUND, ECONNREFUSED), fix server outbound access to api.telegram.org (proxy env vars HTTPS_PROXY/HTTP_PROXY, firewall, DNS) and retry."],"exampleFix":"// before\nconst verification = await TelegramBotService.verifyToken(String(bot_token));\n\n// after - normalize input so pasted quotes/spaces never reach Telegram\nconst verification = await TelegramBotService.verifyToken(\n  String(bot_token).trim().replace(/^[\"']|[\"']$/g, \"\")\n);","handlingStrategy":"validation","validationCode":"// Cheap client-side pre-check before POST /telegram/connect\nconst TELEGRAM_TOKEN_RE = /^\\d{6,}:[A-Za-z0-9_-]{30,}$/;\nfunction assertBotToken(token) {\n  const t = String(token ?? \"\").trim().replace(/^[\"']+|[\"']+$/g, \"\");\n  if (!TELEGRAM_TOKEN_RE.test(t)) throw new Error(\"bot_token must look like <botId>:<hash> from @BotFather\");\n  return t;\n}\n// Out-of-band verify without connecting:\n// const res = await fetch(`https://api.telegram.org/bot${t}/getMe`); if (!res.ok) ...","typeGuard":"function isTelegramBotToken(value) {\n  return typeof value === \"string\" && /^\\d{6,}:[A-Za-z0-9_-]{30,}$/.test(value.trim());\n}","tryCatchPattern":null,"preventionTips":["Trim and de-quote pasted tokens before sending them to /telegram/connect.","Verify a new token with a direct getMe curl before wiring it into the app.","Treat a token as revocable: /revoke in BotFather invalidates old copies, so store the current one in a secret manager, not in code."],"tags":["telegram","bot-token","authentication","validation"],"backgroundTag":"invalid-api-token","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}