06. Troubleshooting
Частые проблемы dev-кластера и их решения. Если твоей нет — проверь tail -f /tmp/lms-api.log, docker logs lms-postgres, Temporal UI (http://127.0.0.1:55480).
Порты заняты
Симптом. make dev-api падает с Address already in use.
Решение.
# Кто занял порт 55400
lsof -i :55400
# Прибить
kill -9 <PID>
# Либо поменяй порт в .env.local:
LMS_API_PORT=55401
То же для 3500 (frontend), 55432 (postgres), 55480 (Temporal UI), 55490/55491 (MinIO).
Контейнер lms-postgres не поднимается
docker logs lms-postgres --tail 50
Часто:
- старый volume с устаревшей схемой —
docker compose --env-file .env.local -f infra/docker-compose.dev.yml down -v(ВНИМАНИЕ:-vсотрёт данные, сначалаscripts/backup_db_to_minio.sh); - конфликт с соседним проектом
lms(без-dev): проверитьdocker ps, filter по точному имениlms-postgres, а не по подстрокеlms.
alembic upgrade падает
Симптом. Ошибка типа relation X already exists или duplicate key.
Решения:
- Сначала бэкап
bash scripts/backup_db_to_minio.sh oops. - Проверить
alembic current— может быть stamped в старое. - Если нужно откатиться —
alembic downgrade <revision>. - Если миграция сломана — поправить файл, один
def upgradeна файл:grep -c "^def upgrade" packages/core/migrations/versions/<file>.py→1.
Никогда не делай на проде alembic stamp head без понимания последствий.
agent_prompts_no_update триггер блокирует UPDATE/DELETE
По дизайну (ADR-0011). Dev-воркэраунд:
ALTER TABLE agent_prompts DISABLE TRIGGER agent_prompts_no_update;
DELETE FROM agent_prompts WHERE slug='...' AND version=...;
ALTER TABLE agent_prompts ENABLE TRIGGER agent_prompts_no_update;
На проде — только добавление новой строки (new version = MAX+1).
FastAPI 500: SET LOCAL app.current_user_id not set
Симптом. Запросы падают с ошибкой от RLS-политики.
Причина. Роутер использовал неправильный движок (superuser вместо lms_app) или забыл get_rls_conn.
Решение. Любой пользовательский роутер → packages.core.db.get_rls_conn(user) (выполняет SET LOCAL).
Webhook'и провайдеров — это системные вызовы без user'а → используют get_db_engine (superuser, обходит RLS).
Frontend: «Session expired» сразу после логина
Причина. access_token не сохранился в sessionStorage (например, SSR-попытка прочитать его).
Проверка. Открыть DevTools → Application → Session Storage → ключ access_token.
Фикс. Все чтения токена — только внутри useEffect / client-компонента.
Next.js hot-reload не подхватывает изменения в frontend/app/globals.css
cd frontend
rm -rf .next
npm run dev
next build падает на TypeScript-ошибке
cd frontend
npx tsc --noEmit # локально до commit
Красные файлы фиксить до пуша. next build должен быть зелёным.
Gemini: «Budget exceeded» / 429
Симптом. llm_client.generate бросает BudgetExceededError.
Решение.
- Проверь
CostReportна/dashboard. - В
.env.local→MAX_DAILY_USDможно поднять (осторожно). - В dev включи
LMS_TEST_MODE=1— тогда Veo/Lyria мок, Nano Banana — cap 3/test. - Если лимит в Google Cloud — там же и поднимай квоту.
Temporal workflow висит
Temporal UI (http://127.0.0.1:55480) → найти workflow → посмотреть последнюю activity.
Если activity падает:
- логи worker:
tail -f /tmp/lms-worker.logилиdocker logs lms-worker; - идемпотентно ли она написана? (см. manifest §7);
- heartbeat есть?
Перезапустить — через Temporal UI (кнопка «Reset» / «Terminate») или повторный вызов кода, запускавшего workflow (через temporalio.client.Client.start_workflow). Готовой CLI-обёртки для перезапуска CourseGenerationWorkflow сейчас нет.
POST /adaptive/supplement возвращает 429
adaptive_daily_cap_reached — норма. Студент исчерпал 5 подсказок/день. В dev лимит можно обойти через SQL:
DELETE FROM adaptive_blocks WHERE for_user_id = '<user-uuid>' AND generated_at::date = CURRENT_DATE;
POST /billing/webhooks/<provider> не срабатывает
Webhook — это серверный вызов, он не требует JWT и обходит RLS (через superuser engine).
Проверки:
- подпись (если провайдер её присылает);
- идемпотентность — вторая доставка возвращает
{status:"duplicate"}, это норма.
В dev-эмуляторе /billing/mock-checkout сам делает fetch('/billing/webhooks/mock', ...).
MCP-сервер не отвечает в IDE
make mcp-test
Чаще всего:
.venvне активирован / пересобран —pip install -e '.[dev]';DATABASE_URLне подгрузился из.env.local— проверьenvFileв.vscode/mcp.json;- сервер упал — стартанёт сам при следующем вызове, но посмотри stderr через IDE-логи.
docker ps | grep lms показывает посторонние контейнеры
На машине может быть соседний проект lms. Никогда не фильтруй по подстроке lms.
# Правильно: ровно наш проект
docker compose --env-file .env.local -f infra/docker-compose.dev.yml ps
# или
docker ps --filter 'name=^lms-(postgres|temporal|temporal-ui|minio)$'
Тесты падают: AttributeError: module ... has no attribute '...'
Часто — кэш pytest.
find . -name __pycache__ -type d -exec rm -rf {} +
.venv/bin/pytest -q tests/
Страница /analytics пустая
- Проверь что ты вошёл под
school_admin@localилиteacher@local;student@localполучит 403. - В поле
course_idнужен именно слаг (как вpublished_courses.course_id), а не UUID.
Браузер говорит «Session Storage quota exceeded»
Почисти через DevTools → Application → Clear storage.
Если ничего не помогло
git status— вдруг локальные правки мешают.git stash→ попробовать на чистом main.- Пересобрать окружение:
docker compose --env-file .env.local -f infra/docker-compose.dev.yml down rm -rf .venv frontend/.next frontend/node_modules # ... и далее по [05-developer.md](05-developer.md) - Последний бэкап БД — в MinIO
s3://db-backups/.