Частые ошибки при разработке Telegram-ботов и как их избежать
Практика3 минРедакция Innovialabs
Коротко
Большинство проблем ботов — это тупиковые меню, состояние в памяти процесса, токен в коде, отсутствие обработки ошибок и админки; их закрывают кнопки «Назад» на каждом экране, Redis или база для состояний, секреты в переменных окружения, общий обработчик ошибок и простая панель управления.
Короткий ответ
Ошибки в ботах делятся на три группы:
- UX — пользователь застревает, не понимает, что делать дальше, или ждёт ответа на кнопку;
- технические — бот теряет данные, падает от лимитов или светит токеном;
- бизнесовые — владелец не может ничего поменять без разработчика и не видит результатов.
Ниже — самые частые ошибки и способы их исправить.
UX-ошибки
| Ошибка | Как исправить |
|---|---|
| Тупиковые меню: из раздела нельзя вернуться | на каждом экране кнопки «Назад» и «В меню», /start всегда возвращает на главный экран |
| Бот молчит на неожиданный текст или стикер | общий обработчик «не понял» с подсказкой и кнопками основных действий |
| Кнопка «крутится» после нажатия | всегда вызывайте answerCallbackQuery, даже без текста |
| Каждое нажатие присылает новое сообщение | для навигации редактируйте текущее сообщение через editMessageText |
| Из анкеты нельзя выйти | кнопка «Отмена» и команда /cancel в любом шаге сценария |
| Длинные простыни текста | короткие сообщения, одно действие на экран, детали — по кнопке |
Технические ошибки
Состояние в памяти. Если шаги анкеты и корзина хранятся в оперативной памяти, после деплоя или падения пользователи начинают заново. Храните состояние в Redis или базе:
import os
from aiogram import Dispatcher
from aiogram.fsm.storage.redis import RedisStorage
storage = RedisStorage.from_url(os.environ["REDIS_URL"])
dp = Dispatcher(storage=storage)
Токен в коде. Токен в репозитории — это полный доступ к боту для любого, кто увидит код. Держите его в переменных окружения или менеджере секретов, а .env добавьте в .gitignore. Если токен утёк, перевыпустите его в BotFather командой /revoke.
Две копии бота на polling. Два процесса, одновременно вызывающие getUpdates, получают ошибку конфликта и теряют апдейты. В продакшне используйте вебхук или гарантируйте один экземпляр. Вебхук и getUpdates одновременно не работают.
Нет обработки ошибок и лимитов. Одно исключение не должно молча ломать сценарий. Подключите общий обработчик, а для отправки учитывайте ответы 429 (ждать retry_after) и 403 (пользователь заблокировал бота):
from aiogram.types import ErrorEvent
@dp.errors()
async def on_error(event: ErrorEvent):
logger.exception("Update failed: %s", event.update.update_id, exc_info=event.exception)
Блокирующий код в асинхронном боте. Синхронный драйвер базы или тяжёлый расчёт в хендлере тормозит всех пользователей. Используйте асинхронные драйверы, а долгие задачи выносите в очередь.
Повторная обработка. При сбоях Telegram может прислать апдейт повторно. Операции с деньгами и заказами делайте идемпотентными — проверяйте, не обработан ли уже этот платёж или заявка.
Нет логов и алертов. Пишите логи с ID пользователя и апдейта, а критические ошибки отправляйте в служебный чат.
Бизнес-ошибки
- Нет админки. Любое изменение цены, текста или рассылка требует разработчика. Минимум: редактирование текстов и каталога, рассылка по сегментам, выгрузка заявок, базовая статистика, роли для сотрудников.
- Нет связи с живым человеком. Сложный вопрос упирается в меню. Добавьте кнопку «Написать менеджеру» с передачей в рабочий чат или CRM.
- Нет аналитики. Без событий «зашёл — выбрал — оплатил» не понять, работает ли бот. Записывайте ключевые действия с первого дня.
- Персональные данные без правил. Если бот собирает телефоны и адреса, нужны согласие пользователя, политика обработки данных и ограниченный доступ сотрудников.
Чек-лист перед запуском
- каждый экран имеет выход назад;
- состояния переживают перезапуск;
- токен и ключи не попадают в репозиторий;
- есть общий обработчик ошибок и алерты;
- владелец может сам менять тексты и делать рассылки;
- ключевые действия пишутся в аналитику.