Решение проблем
Сгруппировано по симптому: что вы видите → почему так → как починить.
Бот запускается, но не получает обновлений
409 Conflict: terminated by other getUpdates request— два процесса делают long-polling одного токена (второйbot.start(), старый контейнер ещё работает, или поллинг при установленном webhook). Запускайте ровно один экземпляр. Если ранее устанавливали webhook, вызовитеbot.api.deleteWebhook()перед поллингом.- Установлен webhook, поэтому поллинг ничего не получает. Webhook и long-polling взаимоисключающи. Вызовите
deleteWebhook, чтобы вернуться к поллингу, либо оставьте webhook и не вызывайте обычныйbot.start(). - Не приходят opt-in обновления (
chat_member,message_reaction,chat_join_request, business-обновления). Telegram исключает их изallowed_updatesпо умолчанию. Передайте их явно:tsСм. Обновления.bot.start({ allowedUpdates: ["message", "chat_member", "message_reaction"] }); - В группах бот видит только команды и @упоминания. Privacy mode включён по умолчанию. Отключите его через
/setprivacyв @BotFather — только если бот должен читать все сообщения группы.
401 / 404 от API
401 Unauthorized— неверный или пустой токен.new Bot(process.env.BOT_TOKEN as string)молча станетundefined, если переменная окружения отсутствует. Убедитесь, что токен загружен (например,node --env-file=.env, dotenv или секреты вашего хостинга) до создания бота.404 Not Foundна каждом методе — обычно неверный базовый URL API (опечатка в кастомном / локальном Bot API) или токен с лишним пробелом/переводом строки.
Сломано форматирование (литеральные теги, нет жирного, двойное экранирование)
Это самые частые ошибки в GramIO — полные правила в Форматировании.
- Вы видите литеральные
<b>/*/ обратные слэши в сообщении. Вы передалиparse_modeвместе с шаблономformat. Никогда не сочетайте их —formatуже создаёт настоящие сущности. Уберитеparse_modeполностью. - Сущности пропадают при объединении массива formattable. Нативный
Array.prototype.join()превращает в строку и срезает сущности. Используйте хелперjoinизgramio. - Сущности пропадают при переиспользовании
FormattableString. Обычная интерполяция шаблона (`${myFormattable}`) срезает сущности; не вызывайте на нём.toString(). Всегда оборачивайте переиспользуемые formattable во внешнийformat`...`. - Форматирование подписи игнорируется на медиа. Передавайте значение
formatкакcaption— и снова, безparse_mode.
Callback-кнопки «сломаны» / висит индикатор
- Инлайн-кнопка показывает индикатор загрузки ~15с. Обработчик не вызвал
answerCallbackQuery. Сделайтеawait ctx.answer()первой строкой каждогоcallbackQuery-обработчика (пустой ответ — это нормально) или установите@gramio/auto-answer-callback-query. См. UX-паттерны §7. callbackQuery-обработчик не срабатывает.callback_dataкнопки не совпадает с матчером обработчика. Предпочтите типизированную схемуCallbackDataи передавайте один и тот же экземпляр в.pack()и вbot.callbackQuery(schema, …). См. Инлайн-клавиатуру.BUTTON_DATA_INVALID.callback_dataпревышает 64 байта. Сократите схему / упаковывайте меньше полей.
Сцены / многошаговые потоки
ctx.sceneundefined / сцены ничего не делают.scenes()требует, чтобыsession()был установлен первым:.extend(session()).extend(scenes([...])). См. Сцены.- Поток молча сбрасывается после деплоя или рестарта. Вы использовали
@gramio/prompt(в памяти) для многошагового потока. Ожидаемый промис умирает вместе с процессом. Используйте.ask()у Сцен (сохраняет шаг + ответы через storage) для всего, что должно пережить рестарт.
Доступ к контексту
ctx.payload/ snake_case-поляundefinedили без типов. Не читайте сырой payload. Каждое поле Telegram — это camelCase-геттер на контексте:ctx.from.firstName,ctx.chatId,ctx.messageId.- Ожидаемый геттер
undefined. Он есть только на соответствующем типе обновления — сначала сузьте черезctx.is("message")или фильтр, затем обращайтесь.
Загрузка файлов
sendPhotoпадает или отправляет литеральную строку пути.MediaUpload.path/url/buffer— асинхронный, его нужноawait:tsУже загруженныйawait ctx.sendPhoto(await MediaUpload.path("./p.jpg"));file_idпередаётся напрямую (безMediaUpload). См. Файлы.
Webhook не срабатывает
- Telegram не обращается к вашему эндпоинту.
bot.start({ webhook: { url } })вызываетsetWebhook, но не запускает HTTP-сервер — вы должны сами смонтироватьwebhookHandler(bot, "<framework>")и выставить его по HTTPS. Проверьте черезbot.api.getWebhookInfo()(смотритеlast_error_message). См. Webhook. - Локальная разработка: Telegram не достучится до
localhost. Используйте туннель (cloudflared / ngrok) и установите webhook на публичный HTTPS-URL.
Не проходит авторизация Mini App (TMA)
- Не проходит валидация
initData. Расхождение часов, неверный токен бота в валидаторе или вы валидируете уже распарсенный объект вместо сырой строкиinitData. Валидируйте сырую строку правильным токеном. См. Mini Apps.
Типы / сборка
- Кастомный
ctx.foo—anyили ошибка. Не дополняйте черезdeclare module. Добавляйте через.derive(ctx => ({ foo }))(на обновление) или.decorate({ foo })(статически), чтобы тип проходил автоматически.
Всё ещё не получается?
- Найдите нужный метод и его таблицу ошибок в справочнике методов Telegram Bot API.
- Спросите в чате GramIO.