Skip to content

Errors

Not observed, specified

The gateway is not deployed, so none of these errors has been returned by a running server. The mapping below comes from the specification. See implementation status.

A failed call still returns HTTP 200 in most client libraries — the failure is in the body:

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

Always branch on ok before touching result. error_code is one of 400, 401, 403, 404, 409, 413, 429, 500 — nothing else.

Retry or not

Most errors are terminal. Retrying a 403 because the user blocked your bot burns rate limit and never succeeds. Only 429, 500 and file is not ready are worth a second attempt.

error_codeErrorRetry
429Too Many Requests: retry after NYes
429Too Many Requests: retry after NYes
400Bad Request: chat not foundNo
403Forbidden: bot is not a member of the chatYes
403Forbidden: bot was blocked by the userYes
400Bad Request: not enough rightsNo
400Bad Request: message is too longNo
400Bad Request: message to reply not foundNo
400Bad Request: message to edit not foundNo
400Bad Request: message can't be editedNo
400Bad Request: message can't be editedNo
400Bad Request: can't parse entitiesNo
400Bad Request: reaction is not allowedNo
403Forbidden: user is bannedNo
413Request Entity Too LargeNo
400Bad Request: wrong file typeNo
400Bad Request: file is not readyYes
401UnauthorizedYes
500Internal Server Error: temporarily unavailableYes
500Internal Server ErrorYes
409Conflict: terminated by other getUpdates requestNo

Reference

Too Many Requests: retry after N

error_code: 429 — core code FLOOD_WAIT (HTTP 429)

Cause. You exceeded a rate limit -- per token, per chat, or per method.

Fix. Read parameters.retry_after and sleep exactly that many seconds. Do not retry sooner and do not retry in a tight loop; every early retry extends the window.

Too Many Requests: retry after N

error_code: 429 — core code SLOW_MODE (HTTP 429)

Cause. The group has slow mode enabled and the bot is not an administrator.

Fix. Honour retry_after. The gateway computes it from the group's slow-mode interval, so it is always present on this error even though the core does not send one.

Bad Request: chat not found

error_code: 400 — core code PEER_NOT_FOUND · NOT_FOUND (HTTP 404)

Cause. The chat_id does not exist, or the bot has never been introduced to it. A bot cannot open a conversation with a person -- the person must message it first.

Fix. Check the sign convention: positive for private chats, negative for groups, -100-prefixed for channels. If the id is right, the bot has simply never met that chat.

Forbidden: bot is not a member of the chat

error_code: 403 — core code PEER_ACCESS_DENIED (HTTP 403)

Cause. The bot was removed from the chat, or never added.

Fix. Re-add the bot. Treat this as terminal for that chat -- stop the queue for it rather than retrying.

Forbidden: bot was blocked by the user

error_code: 403 — core code USER_BLOCKED_YOU (HTTP 403)

Cause. The person blocked the bot.

Fix. Terminal. Mark the user inactive and stop sending -- retrying will not unblock you and counts against your rate limit.

Bad Request: not enough rights

error_code: 400 — core code FORBIDDEN (HTTP 403)

Cause. The bot is in the chat but lacks the specific administrator right the method needs.

Fix. Grant the matching right. getChatMember on the bot's own id shows exactly which rights it currently holds.

Bad Request: message is too long

error_code: 400 — core code TEXT_TOO_LONG (HTTP 422)

Cause. Text exceeded 4096 characters, or a caption exceeded 1024.

Fix. Split on a character boundary, not a byte boundary -- limits are counted in UTF-16 code units, the same unit entity offsets use.

Bad Request: message to reply not found

error_code: 400 — core code REPLY_NOT_FOUND (HTTP 400)

Cause. The message referenced by reply_parameters was deleted, or lives in a different chat from the one you are sending to.

Fix. Send without the reply, or set allow_sending_without_reply inside reply_parameters so the message goes out unthreaded instead of failing.

Bad Request: message to edit not found

error_code: 400 — core code MESSAGE_NOT_FOUND (HTTP 404)

Cause. The target message was deleted, or the id belongs to a different chat.

Fix. Stop editing that id. Keep chat_id and message_id together in your own storage -- a message_id is only unique within its chat.

Bad Request: message can't be edited

error_code: 400 — core code EDIT_TIME_EXPIRED (HTTP 400)

Cause. The 48-hour edit window closed.

Fix. Delete and re-send. For content that updates for longer than two days, send a fresh message instead of editing in place.

Bad Request: message can't be edited

error_code: 400 — core code NOT_YOUR_MESSAGE (HTTP 403)

Cause. A bot may only edit messages it sent itself.

Fix. None -- this is a permission boundary, not a transient failure.

Bad Request: can't parse entities

error_code: 400 — core code ENTITIES_INVALID (HTTP 422)

Cause. Malformed markup, or entity offsets that overlap, cross, or point past the end of the text.

Fix. Offsets are UTF-16 code units. An emoji is 2 units, not 1 -- computing offsets on a UTF-8 byte string is the usual culprit. Escape user-supplied text before interpolating it into Markdown.

Bad Request: reaction is not allowed

error_code: 400 — core code EMOJI_INVALID (HTTP 422)

Cause. The emoji is not in the chat's allowed-reactions list. Groups can restrict reactions to a whitelist, or disable them entirely.

Fix. Read the permitted set from getChat before reacting.

Forbidden: user is banned

error_code: 403 — core code USER_BANNED (HTTP 403)

Cause. The account is banned platform-wide.

Fix. Terminal.

Request Entity Too Large

error_code: 413 — core code FILE_TOO_LARGE (HTTP 413)

Cause. The upload exceeded the size limit for its kind.

Fix. Compress, or send as a document where the limit is higher. The limit is per file kind -- see Limits.

Bad Request: wrong file type

error_code: 400 — core code UNSUPPORTED_MIME · MIME_MISMATCH (HTTP 422)

Cause. The bytes do not match the declared kind. The server sniffs magic bytes and does not trust the extension or the declared Content-Type.

Fix. Send the file with the method that matches its real format, or use sendDocument.

Bad Request: file is not ready

error_code: 400 — core code FILE_NOT_READY (HTTP 409)

Cause. The upload landed but post-processing (thumbnails, waveform, transcode) has not finished.

Fix. Retry after a short delay. This one is genuinely transient.

Unauthorized

error_code: 401 — core code UNAUTHORIZED · SESSION_REVOKED (HTTP 401)

Cause. The token is malformed, revoked, or belongs to a deleted bot.

Fix. Terminal. Check the token; if it was revoked, issue a new one and redeploy. Never retry -- a loop here looks like credential stuffing.

Internal Server Error: temporarily unavailable

error_code: 500 — core code MAINTENANCE (HTTP 503)

Cause. The backend is briefly unavailable, usually a deploy.

Fix. Retry with exponential backoff.

Internal Server Error

error_code: 500 — core code INTERNAL (HTTP 500)

Cause. A fault on our side.

Fix. Retry with backoff. If it persists, report it with the timestamp and the method you called.

Conflict: terminated by other getUpdates request

error_code: 409 — core code (HTTP 409)

Cause. Two processes are polling the same token, or a webhook is registered while you poll.

Fix. Run exactly one poller per token. If you meant to use polling, call deleteWebhook first.

Where these codes come from

GROM runs a Go core that speaks its own error vocabulary; the Bot API gateway translates it into Telegram-compatible codes. The core column above is that mapping, so a report quoting either vocabulary can be traced. The core uses HTTP 422 for validation failures — the gateway collapses those to 400, because Telegram never emits 422 and client libraries do not expect it.