Telegram-бот перестал отвечать: почему и как починить

Бот отвечал вчера, а сегодня молчит: сообщения доходят, ответа нет, и первым делом хочется открыть код. Обычно код тут ни при чём — причина в том, где и как запущен процесс. Ниже диагностика от частых причин к редким: что проверить первым, как читать логи и куда перенести бота, чтобы это не повторялось.

Первое, что нужно проверить: жив ли контейнер

Смотрите на статус процесса, а не на код. В панели Dockbox статус проекта и логи видны в реальном времени, на своём сервере то же показывает Docker:

docker ps -a
docker ps -a --filter status=exited

Exited — вопрос закрыт. Не работающий контейнер отвечать не может, осталось узнать, почему процесс умер: это в логах.

Restarting — тот же молчащий бот. Контейнер крутится в перезапусках и не успевает подняться: до опроса Telegram дело не доходит, а в логах повторяется одна и та же ошибка.

Тишина в логах — тоже диагноз. Если последняя запись — вчера вечером, процесс перестал существовать: его выключили вместе с компьютером или закончился оплаченный период.

Причина 1. Процесс упал: ошибка в коде или зависимостях

Симптом: бот поработал несколько часов и замолк, статус Exited, перед остановкой в логах есть ошибка.

Что происходит. Процесс падает на сообщении, под которое не написан: бот ждал текст, а пришла фотография; обработчик команды бросил исключение. Скрипт без перехвата ошибок завершается на первом исключении — и поднять его некому.

Проверьте зависимости. Классика: в requirements.txt нет библиотеки, которую бот импортирует, или версия устарела. Локально всё работало — пакет стоял в вашем окружении, а в логах ModuleNotFoundError при старте.

Решение. Прочитайте последние строки перед остановкой — там написано, что упало. Дополните requirements.txt и оберните обработчики в try/except, чтобы одно сообщение не убивало бот.

Причина 2. Токен и пустые переменные окружения

Симптом: бот не отвечает вообще, а при старте в логах ошибка авторизации или KeyError.

Токен — это пароль, и он живёт отдельно от кода. Если переменная окружения пуста, а код читает её напрямую, бот падает ещё до подключения к Telegram:

import os
TOKEN = os.environ["BOT_TOKEN"]

Убедитесь, что переменная видна процессу. На своём сервере:

docker exec mybot env | grep BOT_TOKEN

Частый сценарий: код загружен, а переменные в панели не заполнены; либо токен перевыпущен в BotFather, а проект держит старый — бот выглядит рабочим и молчит.

Решение. Токен храните как секрет проекта, а не в коде и не в архиве. Туда же — строку подключения к базе, ключи API и всё остальное, что бот читает через os.environ.

Причина 3. Лимиты Telegram: бот отвечает через раз

Симптом: бот живой, но часть сообщений остаётся без ответа, рассылка доходит не до всех.

Telegram ограничивает темп отправки. Массовая рассылка без паузы принимается частично. Добавьте задержку между отправками — и доходить будет до всех.

Сначала исключите второй экземпляр. Если бот отвечает примерно каждому второму — дело не в лимитах, а в конфликте ниже.

Лимиты — не ваша инфраструктура: это правила платформы Telegram, и лечатся они задержками в коде.

Причина 4. Конфликт 409: работают два экземпляра

Симптом: бот отвечает через сообщение, либо сразу после запуска в логах Conflict: terminated by other getUpdates request.

Что это значит. Telegram выдаёт обновления только одному клиенту на токен. Если бот запущен дважды — на сервере и на ноутбуке, или старый процесс висит в фоне, — копии отбирают апдейты друг у друга, и половина сообщений пропадает.

Как найти копии. Ищите конфликт и запросы обновлений в логах:

docker logs mybot 2>&1 | grep -i "conflict"
docker logs mybot 2>&1 | grep -i "getUpdates"

Решение. Остановите все копии, кроме одной, и проверьте, что старая действительно завершилась. Терминал со скриптом на компьютере закройте — иначе он подключится к тому же токену снова. Экземпляр в другом проекте даст тот же эффект.

Причина 5. Сеть: контейнер не достаёт до Telegram

Симптом: в логах таймауты, ConnectionError, повторяющиеся попытки подключиться.

Что проверить. Доступность api.telegram.org и работу DNS: если сервер не резолвит имена, бот не может ни забрать обновления, ни отправить ответ, хотя процесс остаётся живым.

docker exec mybot getent hosts api.telegram.org
docker exec mybot python -c "import socket; print(socket.gethostbyname('api.telegram.org'))"

Решение. Имя не резолвится — чините DNS. Соединение режется провайдером или firewall — нужна машина с нормальным исходящим доступом.

Как читать логи: что искать

Логи отвечают на вопрос «что случилось» быстрее всего. Смотрите не весь файл, а последние строки перед тишиной:

docker logs mybot 2>&1 | tail -100
docker logs mybot 2>&1 | grep -iE "error|traceback|exception|critical"
docker logs mybot 2>&1 | grep -i "unauthorized"
docker logs mybot 2>&1 | grep -i "memory"

Что означают находки. Traceback и Exception — ошибка в коде: бот упал на конкретном сообщении. Unauthorized или 401 — неверный токен. Conflict — два экземпляра. Убийство процесса по памяти — утечка: бот съедает RAM и получает Killed.

Время последней записи важнее текста: сопоставьте его с тем, что было вокруг — закрылся ноутбук, сервер перезагрузился, кончились деньги.

Как починить поэтапно и не допустить повторения

Шаг 1. Поднимите процесс. Перезапустите контейнер и проверьте /start. Если бот ответил — работает не решение, а перезапуск: причина осталась.

Шаг 2. Уберите причину. Ошибка в логах — правьте код и зависимости. Токен — обновляйте секрет. 409 — оставляйте один экземпляр. Пустые переменные — заполняйте в панели проекта.

Шаг 3. Включите автоперезапуск. Ключевой шаг: бот должен подниматься сам после сбоя. В Docker за это отвечает политика перезапуска:

services:
  bot:
    image: mybot:latest
    restart: unless-stopped
    env_file: .env

Шаг 4. Уберите бота с ноутбука. Пока процесс живёт на вашем компьютере, автоперезапуску помогать нечему: спящий режим, разрыв Wi-Fi и закрытая вкладка терминала гасят бота.

Это берёт на себя Dockbox. Вы загружаете проект, платформа собирает окружение, запускает процесс и поднимает его после падения, логи всегда открыты в панели. Контейнеры работают постоянно, без остановки по часам: Starter — 990 ₽ в месяц при 1 vCPU, 2 GB RAM и 20 GB SSD, причём первый месяц бесплатный; Pro — 2 490 ₽, Team — 4 990 ₽.

Смежные разборы: круглосуточная работа бота, бот на вебхуках, сколько ресурсов нужно боту.

Частые вопросы

Почему бот работал, а потом перестал?

Изменились не бот, а условия вокруг него: компьютер ушёл в сон, оборвалась сеть, закончился оплаченный период или пришло сообщение, под которое бот не был написан. Искать надо в логах и в том, где запущен процесс.

Код не менялся — почему бот всё равно упал?

Код — не единственное, что влияет на работу: упавшая зависимость, перевыпущенный токен, пустая переменная окружения, перезагрузка сервера или неожиданное сообщение в чате ломают процесс без единой правки в исходниках.

Что означает ошибка 409 Conflict в логах?

Это Telegram сообщает, что на один токен подключились два клиента и мешают друг другу забирать обновления. Проверьте, не запущен ли тот же бот на компьютере или в другом проекте, и остановите все копии, кроме одной.

Бот не отвечает, но контейнер работает. Как это возможно?

Значит, процесс жив, а обмен с Telegram не идёт: обрыв связи, неверный токен или ошибка в обработчике, из-за которой часть сообщений отбрасывается. Проверьте лог на таймауты и Conflict.

Как сделать, чтобы бот поднимался сам после падения?

Настроить автоперезапуск: на своём сервере это restart: unless-stopped в Docker или unit-файл systemd. На платформе деплоя этим занимается она сама — проект перезапускается после сбоя, а логи остаются открытыми.