For AI agents: markdown of this page — /docs-content-en/bots/troubleshooting.md documentation index — /llms.txt

Bot platform troubleshooting

If the bot does not reply to messages, start with the sections below. Each scenario is a separate set of checks with ready-to-use curl commands and reference responses from Vibecode.

Diagnostic scenarios


Events do not arrive

Symptom: a user writes to the bot in a Bitrix24 chat, the bot does not reply, GET /v1/bots/:botId/events returns events: [].

Checklist in order

  1. The bot is registered and active. GET /v1/bots/:botId returns success: true with the fields bot.id, bot.code, bot.eventMode. If 404 — the bot is not registered, run POST /v1/bots.
  2. eventMode: "fetch". Checked in the response of step 1. If webhook — events do not arrive via polling, the bot pushes them to webhookUrl.
  3. The bot type matches the scenario. A bot of type bot only receives messages with an @mention and direct messages. To receive all messages in a chat you need the type personal or supervisor — specified at registration in the type field and not changed afterwards. If you expect all messages but the type is bot, events will arrive only on an @mention.
  4. The bot is added to the chat. The bot receives events only from chats it is a member of. For a direct dialog this happens on the user's first interaction with the bot. For a group chat the bot must be added explicitly via POST /v1/bots/:botId/chats/:dialogId/users.
  5. The user is writing to this exact bot. If your Bitrix24 account has several bots, check the code of the bot being addressed in the chat and compare it with the code in the GET /v1/bots/:botId response. Messages to another bot will not land in this bot's queue.
  6. After 5+ empty polls, check the hint field in the GET /v1/bots/:botId/events response. The platform adds a diagnostic hint if the queue has been empty for several polls in a row.
  7. Re-bind the event subscription. If the bot is active (messages are reaching the chats) but the queue is empty and the hint field appeared, call POST /v1/bots/:botId/resubscribe. Re-binding restores delivery and preserves the bindings of Open Channels and the welcome bot, unlike re-registering via POST /v1/bots.

If all 7 items pass but the queue is still empty — it means the Bitrix24 account is not routing events to the bot. Collect the data from the Where to reach out section and submit a ticket.


TOKEN_MISSING with an authorization key

Symptom:

JSON
{ "success": false, "error": { "code": "TOKEN_MISSING", "message": "API key has no tokens configured." } }

Cause

The vibe_app_… key was sent without the Authorization: Bearer <session_token> header. An authorization key works in tandem with a user session token — without Bearer the request has no context on whose behalf to address Bitrix24.

Solution

A personal key vibe_api_… — no Bearer needed:

Terminal
curl https://vibecode.bitrix24.com/v1/bots/42/events \
  -H "X-Api-Key: YOUR_API_KEY"

An authorization key vibe_app_… — Bearer is mandatory:

Terminal
curl https://vibecode.bitrix24.com/v1/bots/42/events \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

Obtaining the USER_SESSION_TOKEN for an OAuth app — see Keys and authorization.

A common source of this error is an application-side event handler that calls the V1 API in response to a delivered event. The handler has no user session, so a vibe_app_ key does not work there — use a personal vibe_api_ key. See Application-side handler.


Empty events in a row

Symptom: the response is correct, there are no errors, but events: [], nextOffset === storedOffset, persisted: false.

What the response fields mean

  • persisted: false — the lastOffset cursor in the Vibecode database did not move, because Bitrix24 did not return a single event.
  • nextOffset === storedOffset — nothing to process.
  • hint appears after 5+ empty polls in a row — a diagnostic hint.

This is normal if

  • the bot was just registered — nobody has written yet
  • the queue is empty — clients have read all messages
  • there is no activity in chats with the bot between polls.

When to move on to diagnostics

If at least one condition holds — go back to the Events do not arrive section:

  • there are unread messages to the bot in the chat
  • more than a minute has passed since the message was sent
  • the hint field appeared.

BITRIX_ERROR: User is not subscribed

Symptom: GET /v1/bots/:botId/events?withUserEvents=true returns 502 with this message.

Cause

User events (types ONIMV2* — chat changes, user reactions) require a separate subscription. Without a subscription the withUserEvents=true parameter does not enable delivery.

Solution

Subscribe once before using withUserEvents=true. The full setup order and the event list — in the User events section.

After subscribing, GET /v1/bots/:botId/events?withUserEvents=true starts returning user events together with bot events in the same array.


INTERNAL_ERROR while polling events

Symptom:

JSON
{ "success": false, "error": { "code": "INTERNAL_ERROR", "message": "Internal server error" } }

What to do

  1. Do not repeat the request right away. Frequent retries without a pause can prolong the error state and themselves become a cause of overload.
  2. Use a growing pause between attempts — start at 5 seconds, double on each next failure, cap at 60 seconds. After a successful response the interval resets to the working value (2-5 seconds between polls).
  3. Do not reset offset. The stored cursor was not affected — continue from the same value. A reset leads to reprocessing already delivered events.
  4. If the error does not go away after several delay cycles — submit a support ticket with the botId, the time of first occurrence, the last successful nextOffset, and the interval between attempts. Do not increase the request frequency "just in case" — it will make things worse.

Ready-to-use template with a growing pause

javascript
const BOT_ID = 42
const API_KEY = 'YOUR_API_KEY'
const BASE = 'https://vibecode.bitrix24.com/v1'

let backoffMs = 5000

while (true) {
  try {
    const res = await fetch(`${BASE}/bots/${BOT_ID}/events`, {
      headers: { 'X-Api-Key': API_KEY },
    })
    const json = await res.json()

    if (!json.success && json.error?.code === 'INTERNAL_ERROR') {
      console.warn(`INTERNAL_ERROR — pause ${backoffMs} ms`)
      await new Promise(r => setTimeout(r, backoffMs))
      backoffMs = Math.min(backoffMs * 2, 60000)
      continue
    }

    backoffMs = 5000
    for (const event of json.data?.events ?? []) {
      // handle the event
    }
  } catch {
    await new Promise(r => setTimeout(r, backoffMs))
    backoffMs = Math.min(backoffMs * 2, 60000)
  }

  await new Promise(r => setTimeout(r, 3000))
}

Bot disabled (BOT_DISABLED)

Symptom:

JSON
{ "success": false, "error": { "code": "BOT_DISABLED", "message": "Bot is disabled (reason: …)" } }

HTTP code — 410 Gone. All bot endpoints are affected: events, messages, chats, commands, update, delete.

Possible causes (the `reason` field)

  • AUTH_FAILURES — 10 consecutive 401 INVALID_CREDENTIALS from Bitrix24. The platform protects the Bitrix24 account from noisy requests and automatically disables a bot with broken authorization.
  • PORTAL_DELETED — the Bitrix24 account was deleted or confirmed unavailable.

Solution

AUTH_FAILURES — call POST /v1/bots/:botId/reauth. The check confirms the bot's access, refreshes the token if needed, and lifts the disabling. If the response is 410 REAUTH_REQUIRED — access cannot be restored automatically, the key must be re-authorized via OAuth or the personal key re-created.

To reset only the authorization error counter, without an access check, use PATCH /v1/bots/:botId with the body {"disabled": false}:

Terminal
curl -X PATCH https://vibecode.bitrix24.com/v1/bots/42 \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"disabled": false}'

PORTAL_DELETED — the bot is restored automatically when the Bitrix24 account returns to the ACTIVE status. Forced enabling via PATCH is not required for this reason.

PATCH … {"disabled": true} is forbidden — it returns 400 DISABLE_NOT_ALLOWED. Disabling is system-imposed; to delete, use DELETE /v1/bots/:botId.


fetch vs webhook differences

Vibecode supports two event delivery modes: fetch (default) and webhook. The mode is set by the eventMode field at bot registration and does not change afterwards.

fetch webhook
How it works The client requests events itself via GET /v1/bots/:botId/events Bitrix24 pushes events as HTTP POST to webhookUrl
Value types Native: number, boolean, null Everything arrives as strings ("1", "true", "") — a consequence of body serialization on the Bitrix24 side
The bot object in an event Without the auth field Contains auth with the Bitrix24 account's OAuth tokens
Timeout None (long-poll) 10 seconds — Bitrix24 waits for a 200 from your server and closes the connection
Redelivery Server-side offset storage — an event cannot be missed No automatic retries on timeout or a 5xx response
Body format JSON in the GET /v1/bots/:botId/events response application/x-www-form-urlencoded in Bitrix24's own format (event=…&data[bot][id]=…&auth[member_id]=…)
When to choose Most scenarios, especially AI agents When you need minimal reaction time and have a publicly accessible server

With eventMode: "webhook", GET /v1/bots/:botId/events always returns an empty array — events are delivered directly to webhookUrl and do not land in polling.

webhook requires a publicly reachable URL

In webhook mode, Bitrix24 sends events as a POST request directly to webhookUrlwithout Vibecode authorization. So webhookUrl must be publicly reachable from the internet.

A Black Hole server with the default OWNER_ONLY access policy does not accept such a request: without a Vibecode session it stops at the tunnel splash page, and the event never reaches the app. For the Black Hole server to accept incoming events, switch it to the PUBLIC policy via PATCH /v1/infra/servers/:id/access-policy. The PUBLIC policy opens the subdomain to everyone without authorization — enable it deliberately. Alternatively, specify an external publicly reachable webhookUrl, not on a Black Hole subdomain.

A server created for an AI agent always stays on the OWNER_ONLY policy — it cannot be changed. For a webhook bot on such a server, use an external publicly reachable webhookUrl.

The server must be running when the event arrives. A sleeping Black Hole server will not receive the event, and there are no delivery retries — for a webhook bot, disable automatic sleep so the server stays available.

The reachability of webhookUrl is not verified at registration — the bot will register even with an unreachable address.


Stickers

Bots cannot send stickers to users. This is a limitation of the Bitrix24 Bot API v2.

Bots can receive stickers: if a user sent a sticker, the ONIMBOTV2MESSAGEADD event arrives, but the message.text field will be empty. You can react to stickers by sending a text message or an attachment via POST /v1/bots/:botId/messages.


Where to reach out

If none of the sections above helped — leave a ticket in the Feedback section. Attach to the ticket:

  • the botId (a number)
  • the full GET /v1/bots/:botId response
  • the last 3 GET /v1/bots/:botId/events responses with the fields nextOffset, storedOffset, persisted, hint
  • the time of the symptom's first occurrence (UTC)
  • the key type (vibe_api_… or vibe_app_…) — without the key itself
  • a screenshot of the chat with the unread message, if any.

See also