Отладка и частые ошибки
Что делать, когда плагин не собирается, не устанавливается, не запускается или делает не то.
Где смотреть, что происходит
Статус плагина
Системная консоль > Плагины > Управление плагинами, список Установленные плагины:
| Надпись под плагином | Что значит |
|---|---|
| Этот плагин работает. | Всё в порядке |
| Этот плагин не включен. | Плагин выключен. Нажмите Включить |
| Не удалось запустить этот плагин. | Серверная часть не стартовала. Причина — в логах сервера |
| Этот плагин несколько раз падал и больше не работает. | Серверная часть падает сразу после запуска. Ищите panic в логах сервера |
Логи
Всё, что серверная часть пишет через p.API.LogInfo, p.API.LogError и т. п., а также ошибки запуска и паники попадают в лог сервера Loop:
- Системная консоль > Отчеты > Журнал сервера — последние записи прямо в интерфейсе. Ищите по ID плагина: у каждой записи плагина есть поле
plugin_id. - Файл
logs/mattermost.logв папке сервера или выводdocker logs <контейнер>— если Loop запущен в Docker.
По умолчанию в лог не попадают сообщения уровня Debug. Чтобы их видеть, системный администратор включает Системная консоль > Окружение > Ведение журнала > Файловый уровень логирования (или Уровень логирования в консоли) = DEBUG.
Консоль браузера
Ошибки клиентской части видны в инструментах разработчика браузера: F12 (⌥⌘I в macOS), вкладка Console. Там же удобно проверить, загрузился ли плагин:
window.plugins['ru.mycompany.hello']
Если в ответ undefined — клиентская часть не загрузилась. Посмотрите ошибки выше в консоли.
Запросы к серверной части плагина видны на вкладке Network: фильтруйте по /plugins/.
Проверка HTTP API без интерфейса
Маршруты серверной части можно вызвать из терминала с персональным токеном:
curl -H "Authorization: Bearer ваш-токен" \
https://your-loop-server.ru/plugins/ru.mycompany.hello/stats
Частые ошибки
Сборка
| Сообщение | Причина и решение |
|---|---|
go is not available | Go не установлен или не найден. Установите Go и проверьте go version в новом окне терминала |
go: go.mod requires go >= 1.24.3 (running go 1.xx; GOTOOLCHAIN=local) | Слишком старая версия Go. Обновите Go или уберите GOTOOLCHAIN=local из окружения — тогда Go сам скачает нужную версию |
This project's package.json defines "packageManager": "yarn@4..." или yarn: command not found | Не включён Yarn 4. Выполните corepack enable |
npm is not available | Не установлен Node.js |
Cannot parse id from plugin.json | Ошибка в plugin.json: лишняя или пропущенная запятая, кавычка. Проверьте файл любым валидатором JSON |
failed to parse manifest: json: unknown field "..." | В plugin.json поле с опечаткой или поле, которого нет в Loop |
golangci-lint: command not found при make или make check-style | Не установлен линтер. Выполните make deps (или brew install golangci-lint). Собрать плагин можно и без него — командой make dist |
Usage Error: Couldn't find a script named "build:watch" (или debug, test) | Проект создан из старой версии шаблона. Добавьте в webapp/package.json в scripts: "build:watch": "vite build --watch", "debug": "vite build --minify false --sourcemap inline", "debug:watch": "vite build --minify false --sourcemap inline --watch", "test": "echo \"no webapp tests\"" |
error:0308010C:digital envelope routines::unsupported | Бывает у старых плагинов на webpack с новым Node.js. Выполните export NODE_OPTIONS=--openssl-legacy-provider и повторите сборку |
Установка
| Сообщение | Причина и решение |
|---|---|
| «Включите загрузку плагинов в config.json» вместо кнопки загрузки | Загрузка плагинов выключена. Нужно PluginSettings.EnableUploads = true в конфигурации сервера — см. Быстрый старт |
Plugins and/or plugin uploads have been disabled при make deploy | То же самое |
MM_SERVICESETTINGS_SITEURL is not set | Нет файла .env или в нём не задан адрес сервера |
one of MM_ADMIN_TOKEN or MM_ADMIN_USERNAME/MM_ADMIN_PASSWORD must be defined | В .env не задан токен |
Invalid or expired session, please login again (код 401) при make deploy | Токен неверный или отозван. Выпустите новый |
403 / «У вас нет соответствующих прав» | Токен принадлежит пользователю без роли системного администратора |
| «Невозможно установить плагин. Плагин с таким же идентификатором уже установлен» | При загрузке через консоль плагин с этим ID уже есть. Удалите старый или используйте make deploy — он заменяет плагин |
Unable to find manifest for extracted plugin (часто на macOS) | В архив попали служебные файлы macOS ._*. Шаблон их удаляет, но если собираете архив сами — выполните export COPYFILE_DISABLE=true перед упаковкой |
| Загрузка отклоняется, а в Управлении плагинами включено Требовать подпись плагина | При этой настройке Loop принимает только подписанные плагины из магазина. Для своего плагина её нужно выключить |
No signature when persisting plugin to filestore в логе (уровень warn) | Это не ошибка: так Loop отмечает любой неподписанный плагин. Ничего делать не нужно |
unsopported plugin server version в логе | min_server_version в plugin.json больше версии Loop. Верните 9.11.0 — см. Манифест |
Запуск
Если под плагином написано Не удалось запустить этот плагин., откройте журнал сервера и найдите записи с ID плагина. Типичные причины:
| Что в логе | Причина и решение |
|---|---|
backend executable not found for environment: linux/arm64 или exec format error | Нет серверной части под систему сервера. Скорее всего, в .env задан MM_SERVICESETTINGS_ENABLEDEVELOPER=true, а сервер на ARM. Уберите переменную и пересоберите |
Текст вашей ошибки из OnActivate | Плагин сам отказался запускаться: например, не заполнены обязательные настройки. Заполните их в Системная консоль > Плагины > «Ваш плагин» и включите плагин снова |
panic: ... и стек вызовов | Серверная часть упала. Чаще всего это обращение к nil: например, к p.sdk или p.botUserID до того, как они заданы в OnActivate. Стек подскажет файл и строку |
RPC call to <Метод> API failed: rpc: can't find method ... | Плагин вызывает метод, которого нет в Loop. См. Совместимость с Mattermost |
Работа
| Проблема | Причина и решение |
|---|---|
| На slash-команду Loop отвечает «Команда с триггером '/hello' не найдена» | Плагин не запущен или RegisterCommand вернул ошибку — проверьте статус и лог |
| Кнопка или панель не появилась | Откройте консоль браузера: ошибки при загрузке плагина видны там. Проверьте, что вызов registry.register... действительно выполняется (например, добавьте console.log). Обновите страницу с очисткой кеша (Ctrl+Shift+R) |
Запрос к серверной части возвращает 401 Not authorized | Запрос пришёл без пользователя. Из клиентской части отправляйте запросы через Client4 (см. Клиентская часть), снаружи — с токеном |
| Изменили код, а ничего не поменялось | Плагин не пересобран или браузер взял старую версию. Выполните make deploy, проверьте версию в списке плагинов и обновите страницу |
| Настройки не применяются | Имя поля в Configuration не совпадает с key в plugin.json, или тип поля не тот (например, string для настройки bool) |
| Сообщение бота подписано «Кто-то», или реакция бота не видна у автора сообщения | Интерфейс не успел подгрузить данные для события, пришедшего в реальном времени. Обновите страницу — всё появится. На других пользователей и на работу плагина это не влияет |
| Бот отвечает сам себе без конца | В хуке MessageHasBeenPosted нет проверки post.UserId == p.botUserID — плагин реагирует на собственные сообщения |
| Loop стал медленно отправлять сообщения | Долгая работа в MessageWillBePosted или другом хуке ...Will.... Вынесите её в MessageHasBeenPosted или в горутину |
Локальный режим
Если сервер Loop запущен на том же компьютере, где вы разрабатываете, токен можно не создавать. Включите в конфигурации сервера локальный режим — ServiceSettings.EnableLocalMode = true (или переменная MM_SERVICESETTINGS_ENABLELOCALMODE=true) — и перезапустите Loop.
Сервер создаст сокет /var/tmp/mattermost_local.socket, и make deploy будет загружать плагин через него без авторизации. Если сокет лежит в другом месте, укажите путь в .env: MM_LOCALSOCKETPATH=/путь/к/сокету.
Локальный режим даёт полный доступ к серверу всем, у кого есть доступ к сокету. Включайте его только на своём компьютере для разработки.
Пошаговая отладка серверной части
Обычно хватает логов. Но если нужно остановить плагин на строке и посмотреть значения переменных, используйте отладчик Delve. Это работает, только когда сервер Loop запущен на том же компьютере, что и отладчик.
1. Подготовьте сервер
Отладчик останавливает плагин, а Loop считает остановившийся плагин зависшим и перезапускает его. Чтобы этого не было:
-
В
config.jsonсервера установитеPluginSettings.EnableHealthCheckвfalse.Теперь Loop не будет перезапускать упавший плагин, и в списке он будет со статусом Работает, даже если упал. Во время отладки следите за логами.
-
Отключите проверку связи в библиотеке
go-plugin, через которую Loop общается с плагинами. Узнайте её версию вserver/go.modрепозитория сервера (строкаgithub.com/hashicorp/go-plugin) и выполните скрипт:patch_go_plugin.shGO_PLUGIN_PACKAGE_VERSION=$1GO_PLUGIN_RPC_CLIENT_PATH=$(go env GOPATH)/pkg/mod/github.com/hashicorp/go-plugin@${GO_PLUGIN_PACKAGE_VERSION}/rpc_client.goif ! grep -q 'mux, err := yamux.Client(conn, nil)' "$GO_PLUGIN_RPC_CLIENT_PATH"; thenecho "Файл уже изменён или строка не найдена"exit 0fichmod u+w "$GO_PLUGIN_RPC_CLIENT_PATH"sed -i '' '/import (/a\"time"' "$GO_PLUGIN_RPC_CLIENT_PATH"sed -i '' '/mux, err := yamux.Client(conn, nil)/c\sessionConfig := yamux.DefaultConfig()\sessionConfig.EnableKeepAlive = false\sessionConfig.ConnectionWriteTimeout = time.Minute * 5\mux, err := yamux.Client(conn, sessionConfig)' "$GO_PLUGIN_RPC_CLIENT_PATH"echo "Готово"chmod +x patch_go_plugin.sh./patch_go_plugin.sh v1.6.1 # подставьте версию из server/go.modСкрипт написан для macOS; на Linux замените
sed -i ''наsed -i. -
Пересоберите и перезапустите сервер Loop.
Эти изменения ослабляют защиту сервера от зависших плагинов. Никогда не делайте их на рабочем сервере.
2. Подключите отладчик
-
Установите Delve:
go install github.com/go-delve/delve/cmd/dlv@latest. -
Соберите плагин без оптимизаций и установите его:
MM_DEBUG=true make deploy -
В отдельном терминале подключите отладчик к процессу плагина:
make attach-headlessDelve будет ждать подключения на порту
2346. Чтобы отлаживать прямо в терминале, вместо этого выполнитеmake attach. -
В VS Code добавьте в
.vscode/launch.jsonконфигурацию и запустите её на вкладке Run and Debug:.vscode/launch.json{"version": "0.2.0","configurations": [{"name": "Attach to Loop plugin","type": "go","request": "attach","mode": "remote","port": 2346,"host": "127.0.0.1","apiVersion": 2}]}В GoLand то же самое делается через Run > Edit Configurations > Go Remote с портом
2346.
Теперь точки остановки в коде плагина срабатывают. Если что-то пошло не так, отключите отладчик в IDE и выполните make reset — он перезапустит плагин и завершит процессы Delve.
Отладка клиентской части
- Ставьте
console.logиdebugger— они работают как в любом веб-приложении. - Соберите плагин с
MM_DEBUG=true make deploy: код не будет сжат, и в инструментах разработчика на вкладке Sources будут видны ваши исходники. - Установите расширение React Developer Tools, чтобы смотреть свойства и состояние компонентов, и Redux DevTools, чтобы видеть действия и данные хранилища — включая хранилище плагина
plugins-<ID плагина>.
Доступ к локальному серверу из интернета
Если плагин получает вебхуки от внешнего сервиса (GitHub, CRM) или использует вход через OAuth, внешний сервис должен достучаться до вашего сервера Loop. Локальный сервер можно временно открыть в интернет через туннель, например ngrok:
ngrok http 8065
Команда выведет адрес вида https://xxxx.ngrok-free.app. Укажите его в Системная консоль > Окружение > Веб-сервер > Адрес сайта, войдите в Loop по этому адресу и используйте его в настройках внешнего сервиса. На бесплатном тарифе адрес меняется при каждом запуске — не забывайте обновлять его в настройках. Запросы и ответы видны в инспекторе ngrok по адресу http://localhost:4040.
Бесплатная альтернатива без регистрации — ssh -R 80:localhost:8065 localhost.run.