Главная /
Документация /
Бот работает локально, но падает на сервере: ModuleNotFoundError и restarting
Бот работает локально, но падает на сервере: ModuleNotFoundError и restarting
На компьютере бот отвечает, после деплоя на Bothost контейнер уходит в restarting или сразу exited. Ниже Python ModuleNotFoundError, отсутствующий .env, неверный главный файл и то, как отличить это от ошибок Node MODULE_NOT_FOUND.
Для людей и ИИ. Каноническая страница: https://bothost.ru/docs/works-locally-fails-on-server · Markdown: https://bothost.ru/docs/works-locally-fails-on-server.md · Индекс: https://bothost.ru/llms.txt
Отвечает на запросы: bot works locally but not on server, bot crashes after deployment, ModuleNotFoundError, No module named, ImportError, attempted relative import, can't open file, KeyError BOT_TOKEN, container restarting.
Node.js Cannot find module '/app/dist/...' и Cannot find module '/app/index.js' разобраны отдельно: справочник ошибок при деплое.
Как устроен запуск на Bothost
Контейнер — Linux. В него попадает код из Git или из архива, зависимости ставятся на сборке из requirements.txt или package.json. Локальное виртуальное окружение, пакеты из pip install «просто в систему» и файл .env с вашего диска в контейнер не копируются.
Платформа передаёт токен и служебные переменные сама: BOT_TOKEN, API_TOKEN, TELEGRAM_BOT_TOKEN, для Discord DISCORD_BOT_TOKEN, плюс PORT, DATA_DIR=/app/data и при включённом домене WEBHOOK_URL. Полный список: переменные окружения.
Сборка и запуск — разные логи.
Что открыть
О чём говорит
Логи сборки
pip install, npm ci, ошибка Dockerfile. Пока сборка красная, процесс бота ещё не стартовал
Логи работы
Первая ошибка после старта процесса: импорт, нет файла, нет переменной, синтаксис
Сообщение об успешной сборке значит только то, что образ собрался. Падение в логах работы при зелёной сборке — тема этой статьи.
Сначала статус
Пока контейнер в restarting, бот не может отвечать в Telegram, держать webhook или писать в базу. Ищите в логах работы первую строку traceback в цикле и сопоставьте её с разделами ниже. Повтор той же ошибки каждые несколько секунд — процесс стартует и сразу завершается, Docker поднимает его снова.
ModuleNotFoundError
Как выглядит
ModuleNotFoundError: No module named 'aiogram'
Варианты той же ситуации: No module named 'dotenv', No module named 'PIL', No module named 'handlers'. Сборка при этом часто успешна: pip отработал по тому requirements.txt, который был в репозитории, и пакета там не было.
Почему локально пакет есть
На компьютере библиотека стоит в venv или в пользовательском site-packages. На Bothost ставится только то, что перечислено в корневомrequirements.txt (или объявлено в pyproject.toml). Команда сборки:
pip install --no-cache-dir -r requirements.txt
Имя в файле и имя в import часто различаются:
В requirements.txt
В коде
python-dotenv
import dotenv
Pillow
import PIL
python-telegram-bot
import telegram
pyTelegramBotAPI
import telebot
discord.py
import discord
Если в файле нет строки, в контейнере нет модуля, даже если на вашей машине python -c "import aiogram" проходит.
Что сделать
Добавьте пакет в корневой requirements.txt и зафиксируйте версию, с которой бот проверен локально:
aiogram==3.13.1
python-dotenv==1.0.1
Без версии на сборке может приехать другой мажор, и падение будет уже на ImportError внутри библиотеки, а не на No module named.
Задеплойте заново. Рестарт контейнера зависимости не доустанавливает: они попадают в образ только при сборке.
Убедитесь, что файл лежит в корне репозитория, а не только в подпапке, если бот собирается из корня.
Это уже не пакет с PyPI. Локально файл находится из-за того, что вы запускаете скрипт из папки проекта и IDE добавляет её в sys.path. В контейнере рабочий каталог /app, а пакет не является пакетом: нет запуска как модуля, или импорт написан относительно запускаемого файла.
ImportError: attempted relative import with no known parent package
появляется, когда файл с from .handlers import router запустили как скрипт (python bot.py), а не как модуль (python -m package.bot). На Bothost команда запуска — это главный файл из настроек. Либо укажите запуск модулем через свой Dockerfile (кастомный Dockerfile), либо замените относительные импорты на импорты от корня проекта, который реально есть в /app.
Регистр букв на Linux важен. import Config не откроет config.py. Windows такой импорт часто прощает. Переименуйте файл и импорт в один регистр и задеплойте снова.
bot crashes after deployment
Нет переменной, которая локально приходит из .env
KeyError: 'BOT_TOKEN'
Token is invalid or not found
Локально токен берётся из .env через python-dotenv или из переменных IDE. Файл .env обычно в .gitignore, в клон на сервере он не входит. load_dotenv() молча ничего не загружает, следующая строка падает.
На Bothost токен уже лежит в BOT_TOKEN. Читайте его напрямую:
import os
token = os.environ["BOT_TOKEN"].strip()
Дополнительные секреты (OPENAI_API_KEY и подобные) добавьте в разделе переменных окружения бота в панели, затем перезапустите контейнер. Коммитить их в репозиторий не нужно.
Если имя в коде другое (TOKEN, TG_BOT_TOKEN), заведите в панели переменную с этим именем или поменяйте код на BOT_TOKEN.
Неверный главный файл
python: can't open file '/app/bot.py': [Errno 2] No such file or directory
В настройках бота или в CMD указан файл, которого нет в корне. Код лежит во вложенной папке (mybot/bot.py), а поле «Главный файл» пустое или содержит bot.py. Укажите путь от корня репозитория, например mybot/bot.py, и задеплойте снова. Как платформа выбирает точку входа: главный файл.
Для Node та же ситуация даёт Cannot find module '/app/index.js'. Это отдельный разбор в справочнике ошибок, вместе с пропадающим dist/ при WORKDIR /app.
Образ Python на платформе может отличаться от версии на компьютере. Конструкция, которая есть только в более новой версии, валит процесс на первой строке. Зафиксируйте совместимый код или соберите образ со своей версией через Dockerfile. В логе сборки видно, какой интерпретатор ставит зависимости.
Процесс сразу завершается без ошибки
В логе есть ваш print и больше ничего, статус exited или restarting. Скрипт дошёл до конца: нет start_polling, client.run, app.run или другого бесконечного цикла. Локально вы этого не замечаете, потому что следом смотрите в консоль и запускаете снова. Бот на сервере должен оставаться запущенным процессом, а не одноразовым скриптом.
bot works locally but not on server
Если процесс всё же running, а не падает, это уже не импорт. Сверьте поведение, которое на компьютере маскируется окружением: