1) Перевірте токен у BotFather і /setcommands, /setprivacy. 2) Залиште один канал апдейтів: webhook або polling (409 = увімкнено обидва). 3) Перевірте getWebhookInfo — last_error_message порожній, хук дає 200 OK < 10 c, без 301/302. 4) Перевірте права в чаті та форму виклику /cmd@YourBot у групі. 5) Увімкніть логи update_id, chat_id, type, handler, duration_ms, reply_status і повторіть тест у PM і тестовій групі. 6) Якщо «тихо» — тимчасово ввімкніть polling і перевірте мережу/TLS/обробник.
Коли всі перевірки пройдені й бот стабільно відповідає, проганяйте воронку на реальних користувачах невеликими хвилями трафіку. Накрутка підписників тг Україна допоможе швидко дати первинний потік для вимірювання p95-відповіді, error rate, CTR команд і конверсії в цільову дію. Подавайте рівномірно 30–60 хвилин, порівняйте метрики до і після та зафіксуйте безпечний темп.
Відкрийте BotFather і переконайтеся, що токен актуальний і ви не робили нещодавно /revoke (відклик токена). Звірте /setcommands і потрібний scope (за замовчуванням/для груп/для особистих чатів) із тим, що прописано в коді. Перевірте /setprivacy: Enabled, якщо бот працює лише за командами, Disabled — якщо читає звичайні повідомлення. У моїй практиці «мовчання» бота в 3 випадках із 10 вирішував саме цей блок.
У бота має бути лише один спосіб приймання подій: або webhook (вебхук), або long polling (опитування). Одночасний запуск дає 409 Conflict і дублікати, тому зупиніть зайвий канал перед тестом. Для polling спочатку викличте deleteWebhook?drop_pending_updates=true, для вебхука зупиніть полер. «Мій швидкий тест»: вимкнути один канал і перевірити, чи зникли дублікати.
Виконайте getWebhookInfo і перевірте url, last_error_message, ip_address. Помилки TLS/timeout/wrong response виправляються на стороні мережі/сертифіката/обробника; відповідь сервера має бути 200 OK швидко (краще до 2 секунд, максимум 10). Без редиректів і HTML-сторінок замість JSON. Я завжди знімаю вебхук із drop_pending_updates і ставлю заново після виправлення.
Приклад запиту й типового відповіді (last_error_message заповнений):
curl -s https://api.telegram.org/bot$TOKEN/getWebhookInfo | jq .{ "ok": true, "result": { "url": "https://your.domain/bot-hook", "has_custom_certificate": false, "ip_address": "149.154.xx.yy", "pending_update_count": 12, "last_error_date": 1731085200, "last_error_message": "SSL routines: certificate verify failed", "max_connections": 40 } }Очікування «після виправлення»: last_error_message відсутнє/порожнє, pending_update_count → 0, хук стабільно відповідає 200 OK < 2 c.
У приваті користувач має почати діалог першим, інакше 403 Forbidden. У групі з увімкненим Privacy Mode команда викликається як /cmd@YourBot, інакше бот її не побачить. Перевірте права «писати/медіа/закріплювати/видаляти» і роль адміністратора там, де це потрібно. Один чек прав часто економить годину дебагу.
Надішліть /start у приват і ту ж команду в «пісочницю» без обмежень. Увімкніть розширений лог: update_id, chat_id, type, handler, duration_ms, reply_status. Якщо апдейтів немає зовсім — шукайте доставку (webhook/polling/TLS), якщо є — перевіряйте логіку/права. Такий «перехресний тест» стабільно показує, де проблема.
Користувач не писав першим, бот заблокований або 403 на sendMessage. Попросіть користувача натиснути /start і обробіть 403 без повторів (не спамте). Перевірте, чи немає ліміту за частотою 429: увімкніть бекофф і черги. У моїх кейсах це вирішувало 8 із 10 «тихих» PM.
Увімкнено Privacy Mode, і команда без згадки не видима, або у бота немає прав писати. У каналі публікувати можна лише з правами адміністратора — це правило платформи. Перевірте обмеження супергрупи: slow mode, антиспам, заборону на посилання/медіа. Тест у пісочниці одразу показує, чи проблема в політиці групи, чи в коді.
Перевірте, чи підписаний хендлер на callback_query і чи не перевищена довжина callback_data. Екрануйте Markdown/HTML у кнопках і переконайтеся, що Content-Type коректний. Перегляньте логи: чи приходить update.callback_query і що з відповіддю на edit/answerCallbackQuery. Часто проблема не в «кнопках», а у валідації payload.
Перевірте 429 Too Many Requests, чергу повідомлень і кількість паралельних воркерів. Дублікати усуваються ідемпотентністю (без повторної обробки) і збереженням last_update_id. Затримки спричиняють ліміти, довгі операції в хендлері або повільний апстрім. Винесіть важке у фон і обмежте паралелізм.
Після /revoke старий ключ одразу стає неактивним — оновіть секрети в env/CI/CD і перезапустіть процеси. Перевірте, чи немає «застряглих» контейнерів зі старим токеном. Переконайтеся, що ви використовуєте правильний токен у staging/prod (часто плутають). У моїй практиці розсинхрон токенів ламав бота на години без жодної помилки в логах.
Якщо потрібно читати звичайні повідомлення в групі — вимкніть /setprivacy (Disabled) і додайте фільтри за чатами/ролями. Інакше використовуйте лише команди та інлайн, а в групі завжди викликайте /cmd@YourBot. Це прозоро для користувачів і передбачувано для вас. Я завжди документую форму виклику команди в README.
Підтримуйте команди окремо для приватних чатів і груп через scope у BotFather. Стежте за локалями описів — інакше клієнти не підказують команди. Перевіряйте, що назви збігаються з кодом і що бот має права для команд, які передбачають публікацію чи видалення. Це дрібниці, але саме вони часто «ламають» функціональність.
Два канали одночасно призводять до 409 Conflict і дублікатів. Тримайте єдину точку прийому апдейтів і усуньте «гонки» між інстансами. Зафіксуйте у .env змінну UPDATES_MODE=webhook|polling і перевіряйте її при релізі. Це заощаджує час і нерви.
Реєструйте вебхук на публічному HTTPS-домені та перевіряйте getWebhookInfo після активації. Поле last_error_message має бути порожнім; відповідь сервера — 200 OK без редиректів. Під час міграцій знімайте «хвіст» drop_pending_updates=true, щоб не отримати лавину старих апдейтів. «Мій порядок»: health → setWebhook → контроль getWebhookInfo.
Для відладки зніміть вебхук і ввімкніть polling із timeout 25–30 секунд. Зберігайте last_update_id і зсувайте offset на +1, щоб не ловити дублікати. Після виправлення поверніть вебхук і вимкніть полер на всіх інстансах. Це усуває конфлікт і робить потік подій передбачуваним.
Сертифікат має бути від публічного CA, із повним ланцюжком (intermediate), коректним SNI (ім’я сервера в TLS) і CN/SAN (домен у сертифікаті). Прострочений, самопідписаний або неповний сертифікат «глушить» вебхук без явних помилок у боті. Швидка перевірка однією командою:
echo | openssl s_client -servername your.domain -connect your.domain:443 -showcerts 2>/dev/null | openssl x509 -noout -issuer -subject -datesЗвірте issuer/subject/dates і збіг CN/SAN із доменом.
Переконайтеся, що reverse-proxy не робить 301/302 і не переписує Host/SNI. Встановіть адекватні timeouts, client_max_body_size і передайте реальні IP-заголовки. Поверніть 200 OK швидко й не надсилайте HTML-сторінки замість «порожньої» відповіді. Логи на рівні проксі значно прискорюють пошук причин.
Створіть /bot-hook/health, який повертає 200 OK, версію білда й uptime. Логуйте час відповіді (duration) і кореляційні мітки, щоб ловити піки. Записуйте вхідне тіло апдейта в debug-лог, щоб відтворювати рідкі події. Це перетворює «містику» на керовану діагностику.
proxy_read_timeout 10s; proxy_connect_timeout 3s; — тримайте відповідь до 10 c, не більше.certificate verify failed.Host, додайте X-Request-Id для трасування.Створіть /bot-hook/health, який повертає 200 OK, версію білда й uptime. Логуйте час відповіді (duration) і кореляційні мітки, щоб відстежувати сплески. Записуйте тіло апдейта у debug-лог, щоб відтворювати рідкі події. Це перетворює «містику» на керований процес діагностики.
Задайте timeout=25–30 і зберігайте last_update_id, зсуваючи offset на +1. Стежте за limit, щоб не створювати порожні запити й не впиратися в ліміти. Такий режим стабільний і економить трафік. У проді polling — тимчасовий захід, але для відладки він ідеальний.
Не допускайте двох полерів на один токен — це дублікати та гонки. Позначайте оброблені update_id (таблиця/Redis) і тримайте хендлери ідемпотентними (повтор безпечний). Будь-які побічні ефекти (платіж, нарахування) — лише після позначки «оброблено». Це практика, яка економить гроші.
Перевіряйте таймаути HTTP-клієнта й проксі, вмикайте бекофф і ретраї для тимчасових збоїв. Дозвольте вихідні підключення до api.telegram.org:443 і перевірте MTU, якщо мережа «рветься». Якщо провайдер блокує трафік — перейдіть на вебхук і моніторте час відповіді. Цей блок часто недооцінюють, а даремно.
Без прав «писати/медіа/закріплювати» бот у групі буде «мовчати», навіть якщо код правильний. Супергрупи додають повільний режим та антиспам, які візуально «приглушують» активність. Дайте боту потрібні права і протестуйте у пісочниці. У моїх проектах це була найшвидша перемога.
403 на sendMessage означає «заблоковано» або чат приватний. Не робіть повторних спроб у цей діалог — це витрачає ліміти і дратує. Зробіть FAQ «як написати боту в особисті повідомлення» і просіть користувача почати чат першим. Це знижує скарги та підвищує довіру.
В канал бот публікує лише як адмін — це не баг, а правило платформи. Увімкніть обговорення, якщо потрібен діалог під постом, і переконайтеся, що бот має право писати в пов’язану групу. Перевірте обмеження на посилання/медіа, щоб пости не відскакували. Ці кроки часто упускають в ТЗ, а потім дивуються «тиші».
Telegram не публікує точні цифри для всіх методів. Нижче — практичні межі та рекомендації; звіряйте з офіційною документацією.
| Область | Орієнтир | Рекомендація |
|---|---|---|
| На чат | ~1–2 повідомлення/сек | Групуйте відповіді, не робіть спам поспіль |
| На бота | ~20–30 повідомлень/сек | Обмежте паралелізм, розподіляйте навантаження |
answerCallbackQuery | короткі відповіді, часті | Не відправляйте «порожні» відповіді, стежте за частотою |
sendMediaGroup | важкі медіа | Перевіряйте розміри/тип, дайте буфер за часом |
Бекоф з джиттером: база 0.5–1.5 с, множити ×2 до 30 с, додавати випадковий джиттер. На 429 знижуйте частоту і ставте в чергу.
Перевіряйте Content-Type: application/json, довжини полів та екранування Markdown/HTML. Валідуйте емодзі, RTL-текст та довгі підписи. Тестуйте крайні випадки заздалегідь — «тихі» 400 не очевидні. Це економить нічні години підтримки.
401 — невірний/відкликаний токен (отримайте новий і оновіть env). 403 — немає прав/користувач заблокував (не робіть повторних спроб, попросіть написати першим). Супроводжуйте ці коди зрозумілими відповідями для користувача та логами для команди. Чесна обробка помилок підвищує довіру.
409 — одночасно увімкнено polling і вебхук (вимкніть один канал). 413 — файл занадто великий (стискайте/ріжте, відправляйте як документ). 429 — перевищено ліміт (черги, бекоф, зниження частоти та батчинг). 5xx — збої апстріму (зовнішній шлюз/сервер), лікується повторними спробами та моніторингом часу відповіді.
Додайте глобальний перехоплювач помилок і перезапуск за watchdog. Фіксуйте падіння та час обробки (duration_ms), щоб бачити «вузькі місця». На зовнішніх викликах — таймаути та повторні спроби з джиттером; користувач повинен бачити дружню відповідь, а не мовчання. Це базова гігієна бота.
Звірте список типів оновлень: message/command, callback_query, inline_query, edited_message, channel_post. Додайте заглушки та логи на неочікувані події — бот не повинен «падати мовчки». За досвідом, забутий callback_query — причина третини «поломок» кнопок. Оновлюйте схему за документацією після релізів Telegram.
Не тримайте довгі операції у вебхуці або поллері — виводьте в чергу/воркери. Обмежте паралелізм і дотримуйтесь ідемпотентності побічних дій (платіж/бонус). Вимірюйте p95/p99 часу відповіді та відводьте важке «у фон». Так бот залишається відзывчивим.
Звірте валідність ключів, квоти та SLA партнерів. На 4xx/5xx застосовуйте «м’яку деградацію» та зрозумілі тексти для користувача, а не мовчання. Тримайте посилання на статус-сторінки провайдерів. Це економить гроші та нерви.
Ставте таймаути на HTTP-клієнтах і повторні спроби за експонентою з джиттером (база 0.5–1.5 с, множити ×2 до 30 с). Увімкніть circuit breaker (автовимикач запитів) на нестабільних напрямках. Актуалізуйте тексти при деградації, щоб зберегти довіру. Я завжди тримаю цей middleware єдиним для всіх зовнішніх викликів.
Валідуйте JSON/форми за схемою та екрануйте спецсимволи (sanitize/escape). Екрануйте Markdown/HTML та емодзі в підписах/кнопках, перевіряйте довжини полів. Ніколи не довіряйте «як у прикладі в інтернеті» — перевіряйте. Це знімає «тихі» 400 та XSS-ризики.
api.telegram.org:443 та статус-сторінок провайдерів.UPDATES_MODE=webhook|polling в .env, валідуйте на CI/CD, щоб другий канал був вимкнений.Відкрийте вихідні до api.telegram.org:443 та вхідні на порт вебхука. Перевірте заголовки Host/SNI на проксі/Cloudflare та відсутність редіректів. Білі списки IP Telegram іноді потрібні у хостера — уточнюйте. Трасівка та перевірка MTU рятували мені тижні пошуку «примарних» таймаутів.
Перевірте A/AAAA-записи та TTL, особливо після міграцій. Несумісність IPv6 викликає таймаути у частини клієнтів — або вмикайте підтримку, або приберіть AAAA. Дочекайтеся поширення DNS перед увімкненням вебхука. Це простий крок, який часто забувають.
Холодний старт функцій вбиває 200 OK — тримайте прогрів, підвищуйте memory/CPU та виносьте важке у фон. Стежте за глибиною черг та часом обробки — це ранній індикатор проблеми. Налаштуйте health та readiness-проби, щоб оркестратор не вбивав здорові воркери. В продакшені це не розкіш, а необхідність.
| Симптом | Причина | Що перевірити |
| Команда не спрацьовує | Токен/команда/локаль | BotFather /token,/setcommands, scope |
| Немає оновлень | Канал/вебхук | getWebhookInfo, 200 OK, drop_pending_updates |
| Кнопка без відповіді | callback не ловимо | Підписка на callback, довжина callback_data |
| Дублі подій | Два поллери/offset | Один поллер, last_update_id, ідемпотентність |
| У групі «тихо» | Privacy/права | /setprivacy, права адміна, форма /cmd@Bot |
| 409 Conflict | Два канали | Зняти вебхук або зупинити polling |
| 429 затримки | Частота/ліміт | Бекоф, черги, зниження частоти |
| 400/403 | JSON/права | Екранування, довжини полів, права в чаті |
| Код/ліміт | Опис | Дія | Розділ |
| 400 | Невірні параметри/Markdown | Валідація JSON/escape | Ліміти та формати |
| 401 | Невірний/відкликаний токен | Оновити токен/env | Токен та BotFather |
| 403 | Немає прав/ЛС заборонений | Права/попросити написати першим | Права та доступ |
| 409 | Конфлікт каналів | Вимкнути один канал | Канал оновлень |
| 413 | Великий файл | Стискати/різати | Ліміти та формати |
| 429 | Перевищено rate limit | Черги/бекоф | Ліміти та формати |
| 5xx | Збої апстріму | Повторні спроби/моніторинг | Мережа та інфраструктура |
Типові фікси (коротко): TLS — викласти intermediate та перевірити SNI/CN; 409 — зняти один канал (deleteWebhook?drop_pending_updates=true) і залишити єдиний приймач; 429 — увімкнути бекоф+черги та знизити частоту.
Спочатку з’ясуйте, який канал активний. Для вебхука: getWebhookInfo → чи немає last_error_message, 200 OK без редіректів → перевірка TLS/DNS. Для polling: один поллер, коректні offset/timeout → логи оновлень. Якщо обидва кроки чисті — дивимося права та код.
Перевірте /setprivacy та форму виклику команди: /cmd@YourBot або reply. Переконайтеся, що бот має права «писати/медіа/закріплювати/видаляти». Подивіться політику супергрупи: повільний режим/антиспам/заборона ботів. У пісочниці проблема відтворюється? Якщо ні — це налаштування групи.
401 — перевипустити токен та оновити env. 403 — права/блок в ЛС; відповідати дружньо і не робити повторних спроб. 429 — знизити частоту, увімкнути черги та експоненційний бекоф з джиттером. 5xx — повторні спроби, моніторинг затримок, деградація функції без мовчання.
Токен оновлено, /setcommands та /setprivacy відповідають сценарію (ЛС/група). Вебхук дає швидкий 200 OK, ланцюжок TLS повний, SNI/CN вірні. Обрано один канал оновлень і зафіксовано в .env/оркестраторі; другий вимкнено. Таймаути/ліміти/черги/моніторинг увімкнено.
Запишіть активний режим (webhook чи polling) та вимкніть другий. Увімкніть розширений лог оновлень та помилок, перезапустіть воркери/контейнер. Тимчасово переходьте на polling, щоб не втрачати події, і паралельно лагодьте вебхук/TLS/код. Після фіксу поверніть вебхук і перевірте, що last_error_message порожній, p95 у нормі.
Поставте алерт на getWebhookInfo.last_error_message != "" (Slack/Email), відстежуйте p95 часу відповіді та частку 5xx. Оновіть README: матриця прав, порядок увімкнення/переключення каналів, команди BotFather. Проведіть ретро, зафіксуйте зміни в change log та перевірте чек-листи команди.
Швидше за все, у групі увімкнено Privacy Mode або у бота немає прав писати/читати. Використовуйте форму /cmd@YourBot або вимкніть приватність, якщо потрібен доступ до звичайних повідомлень. Видайте боту потрібні права і повторіть тест. Якщо в тестовій групі все ок — причина в налаштуваннях цільової групи.
409 означає, що одночасно увімкнено webhook і polling. Вимкніть один канал: deleteWebhook?drop_pending_updates=true або зупиніть поллер, залишивши єдину точку прийому. Перевірте .env та процеси на інстансах, щоб не було «забутих» поллерів. Після фіксу перевірте getWebhookInfo — помилок бути не повинно.
Перевірте підписку на callback_query, довжину callback_data та екранування Markdown/HTML. Логуйте вхідні update.callback_query та відповідь на answerCallbackQuery/editMessage. Якщо подія не приходить — перевіряйте права, антиспам у групі та ліміти частоти. Це найчастіші причини «мовчання» кнопок.
Якщо last_error_message вказує на TLS/timeout/wrong response — лікуйте мережу/TLS/веб-сервер. Перевірте ланцюжок та SNI однією командою openssl s_client (приклад вище), потім повторіть getWebhookInfo. Якщо polling отримує оновлення, а вебхук — ні, код у більшості випадків ні до чого. Після фіксу помилка йде за хвилини.
Дивіться на 429 та частоту викликів методів — можливо, вперлися в ліміт. Перевірте глибину черг та час обробки — це перші індикатори вузьких місць. Увімкніть бекоф з джиттером (база 0.5–1.5 с, ×2 до 30 с) та обмежте паралелізм. За необхідності масштабуйте воркери та оптимізуйте блокуючі ділянки коду.