> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting: Telegram channel errors

> Fix the four classified Telegram errors — invalid bot token, bot already connected, channel not connected, and provider errors — with connect-flow and send-path resolution paths plus a reconnect decision table.

# Troubleshooting: Telegram channel errors

Telegram fails at two distinct layers: when you **connect** a bot to your
organization, or when you **send** through an already-connected bot. The
classified error codes in [the error-codes reference](/reference/error-codes)
split the same way — the first two below are connect-time failures, the other
two are send-time failures. Work the layer that matches the code on the page
before reconnecting anything.

This page covers the channel-level error codes. For send-rejected causes on a
connected bot (`INVALID_RECIPIENT`, `MISSING_REQUIRED_FIELD`,
`RATE_LIMIT_EXCEEDED`, `MESSAGE_SEND_FAILED`), see the
[Telegram channel page](/channels/telegram#common-errors).

## Symptom map

Read the calling surface first: a connect call (`POST /api/v1/telegram/connect-bot`)
fails with one of the two connect codes; a send call (`POST /api/v1/messages/telegram`
or the sandbox `POST /api/v1/telegram/test/send`) fails with one of the two send
codes. The same dashboard badge reads either way.

| Code                             | Fails at           | Most likely cause                                                                                                         |
| -------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| `TELEGRAM_INVALID_BOT_TOKEN`     | Connect            | Token failed the format check or Telegram's `getMe` round-trip — malformed paste, or a token revoked in BotFather         |
| `TELEGRAM_BOT_ALREADY_CONNECTED` | Connect (HTTP 409) | The bot's `bot_id` is already held — by your own org (one bot per org) or by another Orbit organization                   |
| `TELEGRAM_CHANNEL_NOT_CONNECTED` | Send (HTTP 409)    | The organization has no active connected bot — clears after connect, or after the sandbox verification step for test mode |
| `TELEGRAM_PROVIDER_ERROR`        | Send               | Telegram returned a non-2xx (`{ok: false, description}`) or a network failure on `getMe`, `setWebhook`, or `sendMessage`  |

## Connect-flow errors

### 1. `TELEGRAM_INVALID_BOT_TOKEN` — the token did not pass validation

Orbit validates a pasted token in two stages before persisting it: a format
check (`<digits>:<secret>` — a bot id, a colon, the BotFather secret), then a
live `getMe` round-trip against the Telegram Bot API. Either stage failing
rejects the paste with this code. Trailing whitespace from a copy-paste is
trimmed automatically; a pasted BotFather URL, a partial token, or a revoked
token fails.

**Resolution:** confirm the token works directly against Telegram before you
paste it again:

```bash theme={null}
curl "https://api.telegram.org/bot<your-token>/getMe"
```

A healthy token returns `{"ok": true, "result": {"id": 7654321098, "is_bot": true, "username": "…"}}`.
If that call returns `401 Unauthorized`, the token is dead — issue a fresh one
with `/revoke` in [@BotFather](https://t.me/BotFather) and paste the new value.
If `getMe` succeeds but the Orbit paste still fails, you are pasting more (or
less) than the token — paste exactly the `digits:characters` string BotFather
issued.

### 2. `TELEGRAM_BOT_ALREADY_CONNECTED` — the bot is already claimed (HTTP 409)

A connect attempt fails closed when the bot's `bot_id` (the numeric prefix
before the colon) is already registered on an Orbit organization. Two cases:

* **Your own organization already has a bot connected.** One bot per
  organization — the new connect is refused until the existing bot is
  disconnected. This is also the path to rotate a token: you must disconnect
  before you reconnect.
* **Another Orbit organization holds the claim.** Someone (a teammate's other
  org, or a leaked token claimed by a third party) connected this bot first.
  Follow the [ownership dispute recovery paths](/channels/telegram#ownership-disputes)
  on the channel page.

**Resolution:** for your own org, open **Settings → Channels → Telegram** in
the dashboard, open the bot card, and choose **Disconnect**. Then connect
again with **Add bot** — the same two operations are available over the API as
`POST /api/v1/telegram/disconnect-bot` and `POST /api/v1/telegram/connect-bot`.
Conversation history survives the rotation because Orbit keys it by `bot_id`,
not by the token. For another org's claim, disconnect from that org (or work
the ownership-dispute path) before retrying.

## Send-path errors

### 3. `TELEGRAM_CHANNEL_NOT_CONNECTED` — no active bot on the org (HTTP 409)

A send was attempted — a production `POST /api/v1/messages/telegram` call, or
the sandbox `POST /api/v1/telegram/test/send` — while the organization has no
active bot row. In test mode this fires when no chat has completed the sandbox
verification yet; in production mode it fires after a disconnect, or before the
first ever connect.

**Resolution:** read `GET /api/v1/telegram/channel-state`. If `mode` is
`not_connected`, connect a bot (`POST /api/v1/telegram/connect-bot`, or the
dashboard **Settings → Channels → Telegram → Add bot**) before sending. If you
expect the sandbox (test) path, `POST /api/v1/telegram/test/start-verify` and
complete the `/start` deep-link first. Do not gate production sends on the
sandbox verification — the two modes are independent.

### 4. `TELEGRAM_PROVIDER_ERROR` — Telegram returned a non-2xx or a network failure

The call to Telegram's Bot API (`getMe`, `setWebhook`, or `sendMessage`)
returned `{ok: false, description: "…"}` over a non-2xx status, or the network
hop itself failed. The `description` Telegram returns is the root cause — a
revoked token (`401`), chat not found, or Telegram-side outage. A plain network
failure means the request never reached Telegram and is usually transient.

**Resolution:** probe the stored token with the same `getMe` cURL shown above.
If Telegram answers `401`, rotate the token in BotFather and disconnect/reconnect
from **Settings → Channels → Telegram** with the new value. If `getMe` succeeds,
read the error envelope's `description` — Telegram's own wording tells you
which call failed and why. For transient network failures, retry the send;
Orbit already honors Telegram's `retry_after` on flood-control 429s. A
provider error that persists across valid tokens and retried sends belongs in
a support ticket (below).

## Reconnect decision table

Disconnect/reconnect from **Settings → Channels → Telegram** (dashboard **Disconnect**
then **Add bot**, or the API `disconnect-bot` / `connect-bot` pair). A fresh
token reconnect preserves the bot's conversation history — Orbit keys history
by `bot_id`, not by token.

| Situation                                               | Reconnect needed?      | Action                                                                                                           |
| ------------------------------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Token rotated via BotFather `/revoke`                   | Yes                    | Disconnect, then connect with the new token — old tokens stop working immediately                                |
| 409 `TELEGRAM_BOT_ALREADY_CONNECTED` from your own org  | Yes                    | Disconnect first, then connect — that is the whole fix                                                           |
| 409 from another Orbit organization                     | Not from your side     | Work the [ownership dispute path](/channels/telegram#ownership-disputes); support releases the other org's claim |
| `TELEGRAM_PROVIDER_ERROR` with `getMe` returning 401    | Yes                    | Revoke in BotFather, disconnect, connect with a fresh token                                                      |
| `TELEGRAM_PROVIDER_ERROR` with a healthy `getMe`        | No                     | Read the returned `description`; fix the call, not the connection                                                |
| `TELEGRAM_CHANNEL_NOT_CONNECTED` in production mode     | Connect, not reconnect | The org has no active bot — connect one                                                                          |
| `TELEGRAM_CHANNEL_NOT_CONNECTED` in test (sandbox) mode | Verify, not reconnect  | Run `test/start-verify` and complete the `/start` deep link                                                      |

## What not to do

* **Do not retry a connect on an invalid token.** `TELEGRAM_INVALID_BOT_TOKEN`
  is deterministic — paste-validation fails the same way every time. Rotate
  the token in BotFather, then reconnect.
* **Do not force the second-org claim from your dashboard.** A
  `TELEGRAM_BOT_ALREADY_CONNECTED` 409 owned by another organization resolves
  through the [ownership dispute path](/channels/telegram#ownership-disputes)
  only; reconnecting loops the same 409.
* **Do not treat a provider error as a connection problem.** Disconnect and
  reconnect the bot only after `getMe` proves the token is dead; otherwise you
  are solving the payload or the transient network with a credentials reset.

## When to escalate

Open a support ticket when one of these holds:

* `getMe` succeeds against Telegram directly, but connect still returns
  `TELEGRAM_INVALID_BOT_TOKEN` and the pasted value is exactly the issued token.
* `TELEGRAM_PROVIDER_ERROR` persists across freshly rotated tokens and retried
  sends, with a `description` Telegram does not document.
* An ownership dispute where the claim-releasing steps in
  [Ownership disputes](/channels/telegram#ownership-disputes) have been followed
  and the 409 remains.

Include all three so support can pull the Telegram provider trace without a
back-and-forth:

* Your **tenant ID** (dashboard under Settings → Organization, or
  `organizationId` on `GET /api/v1/me`).
* The **bot's `@username`** and the numeric **bot id** (the digits before the
  colon in any token you have held).
* One **request ID** (from the `request_id` envelope field) of a failing,
  non-redacted connect or send call — plus the classified error code it
  returned.

## See also

* [Telegram channel page](/channels/telegram) — send shapes, send-rejected
  causes (`INVALID_RECIPIENT`, `MESSAGE_SEND_FAILED`), token handling, and the
  ownership-dispute process
* [Telegram API reference](/api-reference/telegram) — the channel-state,
  sandbox-verify, and connect/disconnect endpoints this page calls
* [Telegram onboarding guide](/guides/telegram-onboarding) — sandbox bot +
  production bot walkthrough with status tables
* [Error codes reference](/reference/error-codes) — the classified error
  catalog this page decodes
