Troubleshooting
Bot API Errors
400: Bad Request: Cannot parse entities
This error often occurs when sending messages with invalid markup. What does it mean? You are sending a message with Markdown, MarkdownV2, HTML and didn't close the tag somewhere or use reserved characters.
Markup type | Reserved characters |
---|---|
Markdown | _ , * , [ , \ |
MarkdownV2 | _ , * , [ , ] , ( , ) , ~ , < , > , # , + , - , = , \ , | , { , } , . , ! |
HTML | & , < , > |
Very often, many people forget to escape these special characters when inserting text received from users by manual input, nicknames, first name, last name and other data, this can cause this error if they contain reserved characters. We recommend escaping such data with utils included in opengram out of box
const { Extra, Markup: { HTML, md, mdv2 } } = require('opengram')
// ... bot initialization code ...
const firstName = "<My Cool Name>";
bot.help(async ctx => {
// This throws an error
await ctx.replyWithHTML(`<b>${firstName}</b>`)
})
bot.start(async ctx => {
// This work fine, because all special chars escaped
await ctx.replyWithHTML(HTML`<b>${firstName}</b>`) // bold "<My Cool Name>"
})
If you use i18next, it by default escapes HTML characters in strings in interpolation.
400: Bad Request: message is not modified
This error occurs when you try to update a message with data that exactly matches the data in the message. Solutions to this error - ignoring
You can ignore it locally with Promise.catch
or globally with bot.catch
handler
ctx.editMessageText(`Hello, world`)
.catch(console.log)
If you look at the example, we are using console.log
because complete ignoring such as
.catch(Function.prototype)
/ .catch(() => {})
, etc. can cause significant problems when debugging code
400: Bad Request: message can't be deleted for everyone
The deleteMessage
method has some limitations:
- A message can only be deleted if it was sent less than 48 hours ago.
- A dice message in a private chat can only be deleted if it was sent more than 24 hours ago.
- Bots can delete outgoing messages in private chats, groups, and supergroups.
- Bots can delete incoming messages in private chats.
- Bots granted
can_post_messages
permissions can delete outgoing messages in channels. - If the bot is an administrator of a group, it can delete any message there.
- If the bot has
can_delete_messages
permission in a supergroup or a channel, it can delete any message there.
400: Bad Request: message can't be edited
You are most likely getting this error because the bot is trying to edit someone else's message.
401: Unauthorized
Your bot token is wrong or revoked. Check twice is token actual in BotFather
403: Forbidden: bot was blocked by the user
You are getting this error because the user has blocked and stopped the bot, until he unblocks it, you will not be able to send messages. Solutions to this error - ignoring
You can ignore it locally with Promise.catch
or globally with bot.catch
handler
ctx.reply(`Hello, world`)
.catch(console.log)
If you look at the example, we are using console.log
because complete ignoring such as
.catch(Function.prototype)
/ .catch(() => {})
, etc. can cause significant problems when debugging code
403: Bot can't initiate conversation with a user
You receive this error because you try to start conversation before user start the bot (or send to bot any message). Bots can't start conversation first, except if user send join request to chat or channel where bot added as admin and have access to accept / reject join requests
404: Not found
If this happens while starting your bot, then your bot token is wrong or revoked. Check twice is token actual in BotFather
or maybe you try call non-exiting API method
409: Conflict: terminated by other getUpdates request
You're running your bot twice on long polling. You can only run one instance of your bot.
If you think that you only run your bot once, you can just revoke the bot token in BotFather. That will stop all other instances.
429: Too Many Requests: retry after
Most likely you encountered this error while trying to send messages to users. Read an excerpt from the official telegram documentation on the limits in mailings
502: Bad Gateway / 500: Internal Server Error
It's a problem with telegram servers, there's nothing you can do about it
Other
My bot crashes due to an error even though I use bot.catch
handler
There can be two problems:
- The bot crashes due to errors in external code that is not related to opengram, user code or user libraries and modules
- The problem is incorrectly returning
Promise
objects in middleware, handlers, etc. (broken promise chain)
First problem not related to Opengram, solution depends on code.
But we can show how to deal with the second problem:
Examples of wrong code ❌
bot.on('message', (ctx) => {
// Promise not awaited and not returned
ctx.reply('Hello, world!')
})
bot.on('message', (ctx) => {
// Promise not awaited and not returned, if enter handler exists and throw an exception,
// it can't be handled by Opengram error handler
ctx.scene.enter('SCENE_NAME')
})
bot.on('message', async (ctx) => {
// First promise awaited, but second not
await ctx.reply('Hello, world!')
ctx.scene.enter('SCENE_NAME')
})
Examples of good code ✅
bot.on('message', async (ctx) => {
await ctx.reply('Hello, world!')
})
bot.on('message', (ctx) => {
await ctx.scene.enter('SCENE_NAME')
})
bot.on('message', async (ctx) => {
await ctx.reply('Hello, world!')
await ctx.scene.enter('SCENE_NAME')
})
bot.on('message', async (ctx) => {
await Promise.allSettled([
ctx.reply('Hello, world!'),
ctx.scene.enter('SCENE_NAME')
])
})
How can I catch completely any error in my code and handle it?
Many people ask how this can be done. It's possible.
However, such processing can cause unexpected consequences, violation of the consistency of data, common state, closures in the code. Typically, this processing is used in order to exit correctly and exit with an error code for the subsequent restart of the application from scratch with a higher-standing tool, such as pm2, docker, systemctl, forever
// Handle all unhandled Promise rejections
process.on('unhandledRejection', (reason, promise) => {
console.log(`Unhandled Rejection at Promise`, reason)
// ... Error processing ...
})
// Handle all unhandled exeptions
process.on('uncaughtException', err => {
console.log(`Uncaught Exception thrown`, err)
// ... Error processing ...
});
You can add it on top of your entry file to handle all unhandled rejections and exceptions. But be careful!
My bot working, but doesn't answer
- This problem can occur when you handle errors incorrectly, it happens that long-polling is stopped and the bot does not receive updates, however, some user code does not allow the process to complete (setTimeout, setInterval, other async ops), as a result, the bot doesn't answer. What can I do?
- Get info about current count pending updates, by calling
getWebhookInfo,
check pending updates increases on new messages.
- Add additional logs for catch this problem in future
- Try to reproduce the problem with added logs
- As temporary solution you can try drop all pending updates if it not contain important information, by calling deleteWebhook
- Perhaps somewhere an error occurs that you simply ignore, this is also one of the varieties of the first point
- Double check all the places where you ignore errors, for good you should log them
- Telegram problems (It happened that for some reason the bot did not receive updates from telegram at all)
- Try to revoke and create a new token
- Create new bot and try with it, if it not works, and no code errors find, echo bot example not works, maybe you can contact with telegram support
Telegram returns number with and without "+" when I receive contact event
This is a known Telegram side problem, you can use code like this, to solve this:
bot.on('contact', (ctx) => {
const { phone_number, user_id } = ctx.message.contact
// Make number always without "+"
const phoneNumber = phone_number.replace('+', '')
//...
})
or globally by creating upstream middleware:
bot.on('contact', (ctx, next) => {
const contact = ctx.message.contact
// Make number always without "+"
contact.phone_number = contact.phone_number.replace('+', '')
return next()
})
I can't solve my problem :(
Something missing?
Check Contributing page.