telega/error

Types

What a Bot API failure actually was, in a form you can case on.

The Bot API has no structured error codes: everything but the HTTP status arrives as English prose in description. classify does that reading once, so call sites match on a constructor instead of spelling substrings of their own. Every is_* predicate in this module is a one-line wrapper over it.

case error.classify(err) {
  error.BotBlocked | error.UserDeactivated -> forget_user(chat_id)
  error.TooManyRequests(retry_after:) -> sleep(retry_after * 1000)
  error.ChatMigrated(new_chat_id:) -> resend_to(new_chat_id)
  _ -> log(err)
}
pub type ApiErrorKind {
  BotBlocked
  BotKicked
  UserDeactivated
  ChatNotFound
  ChatWriteForbidden
  MessageNotModified
  MessageNotFound
  MessageCantBeEdited
  MessageTooLong
  TooManyRequests(retry_after: Int)
  ChatMigrated(new_chat_id: Int)
  Unauthorized
  Forbidden
  BadRequest
  ServerError
  Other
}

Constructors

  • BotBlocked

    The user blocked the bot (403). They can unblock it later, so the chat id stays valid.

  • BotKicked

    The bot was removed from the chat (403 “bot was kicked” / “bot is not a member”).

  • UserDeactivated

    The account is gone for good (403 “user is deactivated”).

  • ChatNotFound

    Telegram does not know this chat (400 “chat not found”) — a wrong id, or a user who never started the bot.

  • ChatWriteForbidden

    The bot is in the chat but may not post there: restricted by an admin, a channel it is not an admin of, or a bot-to-bot chat.

  • MessageNotModified

    The edit was a no-op: new content equals the current one. Safe to treat as success.

  • MessageNotFound

    The message to edit no longer exists (deleted by the user or too old).

  • MessageCantBeEdited

    The message exists but cannot be edited (e.g. not sent by the bot).

  • MessageTooLong

    The text or caption exceeded Telegram’s length limit. Split it and resend.

  • TooManyRequests(retry_after: Int)

    Flood control (429). retry_after is what Telegram asked for, in seconds, or 0 when it sent no parameters.

  • ChatMigrated(new_chat_id: Int)

    The group became a supergroup and got a new id. Resend to new_chat_id.

  • Unauthorized

    The token is wrong or revoked (401).

  • Forbidden

    A 403 this module does not recognize more precisely.

  • BadRequest

    A 400 this module does not recognize more precisely.

  • ServerError

    Telegram’s own failure (5xx). Worth retrying.

  • Other

    Anything else, including every non-API TelegaError (a transport failure, a decode error, an actor that would not start).

pub type TelegaError {
  TelegramApiError(
    error_code: Int,
    description: String,
    parameters: option.Option(types.ResponseParameters),
  )
  FetchError(error: String)
  JsonDecodeError(error: json.DecodeError)
  BotHandleUpdateError(reason: String)
  ApiToRequestConvertError
  SetWebhookError
  RegistryStartError(reason: String)
  BotStartError(reason: actor.StartError)
  ChatInstanceStartError(reason: actor.StartError)
  FileNotFoundError
  DecodeUpdateError(reason: String)
  UnknownUpdateError(update: types.Update)
  ActorError(reason: String)
  RouterError(reason: String)
  SupervisorStartError(reason: actor.StartError)
  ShutdownError(reason: String)
}

Constructors

  • TelegramApiError(
      error_code: Int,
      description: String,
      parameters: option.Option(types.ResponseParameters),
    )

    Returned by Bot API if server returns ok: false, indicating that your API request was invalid and failed.

    parameters is Telegram’s own ResponseParameters when it sent one — retry_after on a flood wait, migrate_to_chat_id when a group became a supergroup. Read them with retry_after / migrate_to_chat_id.

  • FetchError(error: String)

    Returned if the Bot API server could not be reached or the request failed

  • JsonDecodeError(error: json.DecodeError)

    Returned if the JSON response from the Bot API could not be decoded

  • BotHandleUpdateError(reason: String)

    Returned if the bot failed to call handle_update

  • ApiToRequestConvertError

    Returned if the bot failed to convert API request to HTTP request

  • SetWebhookError
  • RegistryStartError(reason: String)
  • BotStartError(reason: actor.StartError)
  • ChatInstanceStartError(reason: actor.StartError)
  • FileNotFoundError
  • DecodeUpdateError(reason: String)
  • UnknownUpdateError(update: types.Update)

    Occurs when the update is not handled by any handler

  • ActorError(reason: String)

    General actor error (e.g., from polling)

  • RouterError(reason: String)
  • SupervisorStartError(reason: actor.StartError)
  • ShutdownError(reason: String)

Values

pub fn classify(error error: TelegaError) -> ApiErrorKind

Read a Bot API failure into an ApiErrorKind.

Non-API errors — transport, decoding, startup — classify as Other: they carry no Telegram status to read.

pub fn is_bot_blocked(error error: TelegaError) -> Bool

The user blocked the bot (403). They can unblock it later, so the chat id stays valid.

pub fn is_bot_kicked(error error: TelegaError) -> Bool

The bot was removed from the chat (403 “bot was kicked” / “bot is not a member”).

pub fn is_chat_not_found(error error: TelegaError) -> Bool

Telegram does not know this chat (400 “chat not found”) — a wrong id, or a user who never started the bot.

pub fn is_chat_unreachable(error error: TelegaError) -> Bool

This chat cannot be delivered to right now: blocked, deactivated, kicked, unknown to Telegram, or one the bot may not write in. Retrying the same call will not help, which is what separates it from a flood wait or a 5xx.

pub fn is_message_cant_be_edited(
  error error: TelegaError,
) -> Bool

The message exists but cannot be edited (e.g. not sent by the bot).

pub fn is_message_not_found(error error: TelegaError) -> Bool

The message to edit no longer exists (deleted by the user or too old).

pub fn is_message_not_modified(error error: TelegaError) -> Bool

The edit was a no-op: new content equals the current one. Safe to treat as success.

pub fn is_message_too_long(error error: TelegaError) -> Bool

The text or caption was longer than Telegram accepts (400 “message is too long”).

pub fn is_user_deactivated(error error: TelegaError) -> Bool

The account is gone for good (403 “user is deactivated”).

pub fn migrate_to_chat_id(
  error error: TelegaError,
) -> option.Option(Int)

The supergroup id this chat was migrated to, as Telegram reported it in parameters.migrate_to_chat_id. Resend to this id instead.

pub fn retry_after(
  error error: TelegaError,
) -> option.Option(Int)

Seconds to wait before repeating the request, as Telegram reported them in parameters.retry_after (flood control). None for every other error.

pub fn to_string(error: TelegaError) -> String
pub fn try(
  result: Result(a, TelegaError),
  to to_error: fn(TelegaError) -> e,
  fun fun: fn(a) -> Result(b, e),
) -> Result(b, e)

Helper to replace result.try for api call and error mapping.

Search Document