Skip to main content

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 typeReserved characters
Markdown_ , * , [ , \
MarkdownV2_ , * , [ , ] , ( , ) , ~ , < , > , # , + , - , = , \, |, { , }, ., !
HTML&, <, >
tip

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>"
})
tip

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

tip

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

tip

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?

note

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 :(

Welcome to chats and discussions!

🇷🇺 RU / 🇺🇦 UA chat: @opengramjs

🇺🇸 EN chat: @opengram_en

🌐 GitHub Discussions

Something missing?

Check Contributing page.