Telegram Bot API reference

Telegram Bot API errors, one by one

40documented codes
8categories
2026-08-20last verified

Last verified against Telegram Bot API reference

Telegram does not publish a numbered error table the way WhatsApp or Discord do. A failed Bot API call returns an HTTP status in error_code and a short, literal description string, and the documentation explicitly says the numeric code is subject to change. In practice the description is stable and it is what developers search for, so this page is organized by description: one entry per distinct string, grouped under the status that carries it. Where a description varies (a byte offset, a retry time, the chat type the bot was kicked from) the stable prefix is listed and the variable part is marked.

Errors come back in the response body of the method you called. Webhook delivery failures are different: those surface in getWebhookInfo as last_error_message, not as a response to your request, and are covered in Telegram bot not responding and the webhook debugging guide. Two errors also carry a machine-readable parameters object (the ResponseParameters type): 429 includes retry_after (seconds to wait) and the supergroup migration error includes migrate_to_chat_id (the replacement chat ID). Log the full body, not just the status; Telegram's descriptions are short but precise.

Client libraries wrap these responses in their own exception types: python-telegram-bot raises Conflict, Forbidden, RetryAfter or ChatMigrated; aiogram raises TelegramConflictError, TelegramForbiddenError, TelegramRetryAfter or TelegramMigrateToChat; Telegraf and grammY throw error objects carrying error_code, description and parameters; node-telegram-bot-api prefixes messages with ETELEGRAM. Each entry below names the wrapper where it helps you search. Every string was checked against the Bot API reference and FAQ and against the literal matchers used by the major client libraries. Status-only entries (502, 504) come from Telegram's front-end proxy and return HTML rather than JSON. Related: Telegram Bot API limits and the bot token checker.

How to read a Telegram error

Every Bot API response is a JSON object with a Boolean ok. On failure, ok is false, error_code repeats the HTTP status (the docs say its contents are subject to change), and description carries the human-readable string this page is indexed by. Some errors add a parameters object of type ResponseParameters with up to two fields: retry_after, 'the number of seconds left to wait before the request can be repeated' after flood control, and migrate_to_chat_id, the supergroup ID that replaced a migrated group (up to 52 significant bits, so store it in a 64-bit integer). The three shapes:

{
  "ok": false,
  "error_code": 409,
  "description": "Conflict: terminated by other getUpdates request; make sure that only one bot instance is running"
}

{
  "ok": false,
  "error_code": 429,
  "description": "Too Many Requests: retry after 34",
  "parameters": { "retry_after": 34 }
}

{
  "ok": false,
  "error_code": 400,
  "description": "Bad Request: group chat was upgraded to a supergroup chat",
  "parameters": { "migrate_to_chat_id": -1001234567890 }
}

All 40 codes

Jump to: 400 Bad Request: identifiers, content and rights (19) · 400 Bad Request: files and media (5) · 400 Bad Request: webhook registration (3) · 401 / 404: token and path (2) · 403 Forbidden: blocked, kicked, not started (6) · 409 Conflict: getUpdates and webhooks (2) · 429 Too Many Requests (1) · 502 / 504: Telegram-side (2)

400 Bad Request: identifiers, content and rights

CodeTitleHTTPType
400Bad Request: chat not found
Bad Request: chat not found
400Permanent - do not retry
400Bad Request: user not found
Bad Request: user not found
400Permanent - do not retry
400Bad Request: message not found
Bad Request: message not found
400Permanent - do not retry
400Bad Request: message to delete not found
Bad Request: message to delete not found
400Permanent - do not retry
400Bad Request: message can't be deleted
Bad Request: message can't be deleted
400Permanent - do not retry
400Bad Request: message can't be edited
Bad Request: message can't be edited
400Permanent - do not retry
400Bad Request: message is not modified
Bad Request: message is not modified: specified new message content and reply markup are exactly the same as a curren…
400Permanent - do not retry
400Bad Request: can't parse entities
Bad Request: can't parse entities: <detail varies>
400Permanent - do not retry
400Bad Request: message text is empty
Bad Request: message text is empty
400Permanent - do not retry
400Bad Request: message is too long
Bad Request: message is too long
400Permanent - do not retry
400Bad Request: message to be replied not found
Bad Request: message to be replied not found
400Permanent - do not retry
400Bad Request: chat_id is empty
Bad Request: chat_id is empty
400Configuration
400Bad Request: have no rights to send a message
Bad Request: have no rights to send a message
400Configuration
400Bad Request: not enough rights to send text messages to the chat
Bad Request: not enough rights to send text messages to the chat
400Configuration
400Bad Request: CHAT_WRITE_FORBIDDEN
Bad Request: CHAT_WRITE_FORBIDDEN
400Configuration
400Bad Request: group chat was upgraded to a supergroup chat
Bad Request: group chat was upgraded to a supergroup chat
400Configuration
400Bad Request: query is too old and response timeout expired or query ID is invalid
Bad Request: query is too old and response timeout expired or query ID is invalid
400Permanent - do not retry
400Bad Request: BUTTON_URL_INVALID
Bad Request: BUTTON_URL_INVALID
400Permanent - do not retry
400Bad Request: BUTTON_DATA_INVALID
Bad Request: BUTTON_DATA_INVALID
400Permanent - do not retry

400 Bad Request: files and media

CodeTitleHTTPType
400Bad Request: wrong file identifier/HTTP URL specified
Bad Request: wrong file identifier/HTTP URL specified
400Permanent - do not retry
400Bad Request: wrong remote file identifier specified
Bad Request: wrong remote file identifier specified: <detail varies>
400Permanent - do not retry
400Bad Request: file is too big
Bad Request: file is too big
400Permanent - do not retry
400Bad Request: PHOTO_INVALID_DIMENSIONS
Bad Request: PHOTO_INVALID_DIMENSIONS
400Permanent - do not retry
400Bad Request: failed to get HTTP URL content
Bad Request: failed to get HTTP URL content
400Retryable

400 Bad Request: webhook registration

CodeTitleHTTPType
400Bad Request: bad webhook: HTTPS url must be provided for webhook
Bad Request: bad webhook: HTTPS url must be provided for webhook
400Configuration
400Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443
Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443
400Configuration
400Bad Request: bad webhook: failed to resolve host
Bad Request: bad webhook: failed to resolve host: <detail varies>
400Configuration

401 / 404: token and path

CodeTitleHTTPType
401Unauthorized
Unauthorized
401Configuration
404Not Found
Not Found
404Configuration

403 Forbidden: blocked, kicked, not started

CodeTitleHTTPType
403Forbidden: bot was blocked by the user
Forbidden: bot was blocked by the user
403Permanent - do not retry
403Forbidden: bot was kicked from the group chat
Forbidden: bot was kicked from the group chat
403Permanent - do not retry
403Forbidden: bot can't initiate conversation with a user
Forbidden: bot can't initiate conversation with a user
403Permanent - do not retry
403Forbidden: user is deactivated
Forbidden: user is deactivated
403Permanent - do not retry
403Forbidden: bot is not a member of the channel chat
Forbidden: bot is not a member of the channel chat
403Configuration
403Forbidden: bot can't send messages to bots
Forbidden: bot can't send messages to bots
403Permanent - do not retry

409 Conflict: getUpdates and webhooks

CodeTitleHTTPType
409Conflict: terminated by other getUpdates request
Conflict: terminated by other getUpdates request; make sure that only one bot instance is running
409Configuration
409Conflict: can't use getUpdates method while webhook is active
Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first
409Configuration

429 Too Many Requests

CodeTitleHTTPType
429Too Many Requests: retry after N
Too Many Requests: retry after 34
429Retryable

502 / 504: Telegram-side

CodeTitleHTTPType
502502 Bad Gateway
502 Bad Gateway (HTML body from the api.telegram.org front end; not a JSON Bot API response)
502Retryable
504504 Gateway Timeout
504 Gateway Timeout (HTML body from the api.telegram.org front end; not a JSON Bot API response)
504Retryable

Telegram guides and tools

Other platforms

Frequently asked questions

Why doesn't Telegram have numeric error codes like WhatsApp or Discord?

The Bot API returns the HTTP status in error_code and a human-readable description, and the documentation states the numeric code is subject to change. The description string is the stable part and is what client libraries match on. This page is therefore indexed by description rather than by a code table.

What does 'Conflict: terminated by other getUpdates request' mean?

Two processes are long-polling getUpdates with the same bot token. Telegram allows one poller per token, terminates the older connection, and each instance then receives only some updates. Stop every extra instance (local shells, extra replicas, old deploys) or switch to webhooks behind a load balancer.

How do I fix 'can't use getUpdates method while webhook is active'?

A webhook is registered on the token. Call getWebhookInfo to see it, then deleteWebhook (optionally with drop_pending_updates=true) before polling. Webhooks and getUpdates are mutually exclusive per the Bot API documentation.

What is the difference between 'bot was blocked by the user' and 'bot can't initiate conversation with a user'?

Blocked means the user started your bot and then blocked it; stop sending until they return. Can't initiate means the user has never started your bot; a bot may not message anyone first, so they must send /start or tap a deep link before you can write to them.

How should I handle 429 'Too Many Requests: retry after N'?

Read parameters.retry_after and wait exactly that many seconds before retrying. Keep sends under roughly one message per second per chat, 20 per minute per group and about 30 per second overall, as the FAQ describes. Paid Broadcasts in @BotFather raise the bulk limit to 1000 per second for a fee in Stars.

Why do I get 'chat not found' for a user ID I know is correct?

A bot can only address chats it has already seen. If the user never pressed Start, or the ID came from another bot, another system, or was truncated to 32 bits, Telegram cannot resolve it for this bot. For groups, check whether the chat was upgraded to a supergroup and now has a -100 prefixed ID.

What does 'can't parse entities' mean and how do I avoid it?

Your text does not parse under the parse_mode you set. MarkdownV2 requires escaping many punctuation characters; HTML allows only a small tag set and needs & < > escaped. Escape all interpolated content, or send plain text with an entities array. The byte offset in the description points at the failure.

Is a 502 or 504 from api.telegram.org my fault?

No. Those come from Telegram's front-end proxy and usually carry an HTML body rather than the JSON error object. Retry with backoff, guard your JSON parsing, and for sends consider whether a retry could duplicate a message that actually went through.

What is the parameters object (retry_after, migrate_to_chat_id) in a Telegram error?

Some errors include a ResponseParameters object alongside the description. retry_after appears on 429 responses and is the number of seconds to wait before repeating the request. migrate_to_chat_id appears when a group was upgraded to a supergroup and holds the replacement chat ID, which can exceed 32 bits, so store it as a 64-bit integer. Always decode parameters, not just the description.

Why does my library show TelegramConflictError or ETELEGRAM instead of a Telegram error code?

Client libraries wrap the raw JSON in their own exception types. python-telegram-bot raises Conflict, Forbidden, RetryAfter, ChatMigrated or InvalidToken; aiogram raises TelegramConflictError, TelegramForbiddenError, TelegramRetryAfter or TelegramMigrateToChat; Telegraf and grammY throw errors carrying error_code, description and parameters; node-telegram-bot-api prefixes messages with ETELEGRAM. The underlying description string is identical across all of them.

Run your Telegram bot without babysitting error codes

Conferbot manages the connection, tokens, webhooks and retries, and shows failures as readable status.