Если не работает
Реальные отказы snens: симптом, причина, что сделать.
Инструменты и память
Тула нет в списке: [snens] тул <имя>: пустой --help или --help вернул код 1. Причина: реестр читает у тула --help и требует код 0 и непустой stdout; справка в stderr или выход с ошибкой тул прячут. Кривой schema.json тул не теряет — он остаётся на generic-контракте, причина видна в stderr. Что сделать: печатать --help в stdout и завершаться кодом 0, проверить ./tools/<имя>/<имя> --help руками.
Память молчит: справки на ход нет, запись не идёт. Причина: канала нет — бинарь не нашёлся, enabled = false или cmd пуст. Имя без слэша ищется рядом с ядром и в bin/ каталога данных, путь со слэшем — буквально. Что сделать: snens memory покажет enabled/recall/retain/cmd, дальше snens memory on, бинарь на место или memory_cmd путём. Имени нет в каталоге — не ошибка: память выключена.
Конфиг и провайдеры
400 invalid: неизвестный ключ настройки / model: модель задаёт активный профиль. Причина: правятся только известные ключи (опечатка — отказ, а не тихая запись в никуда); при активном профиле base_url/model/key_env берутся из его секции, и правка top-level model не подействовала бы. Что сделать: имя ключа копировать из snens config (max_turns=0 валидно, max_turn=0 — нет); модель менять в профиле (snens providers).
409 exists: имя занято / 409 conflict при удалении профиля. Причина: имя уже есть в [providers]; удаляют активный профиль, а ядро осталось бы без рабочего адреса. Что сделать: PUT /v1/providers/{name} (без key он ключ не стирает) или другое имя; перед удалением переключиться на другой профиль через …/activate.
500 config: … Причина: файл не записался или перестал разбираться; запись атомарная (временный файл → проверка разбора → rename), поэтому правка откатывается целиком. Что сделать: проверить права на config.toml и место на диске; snens config покажет прежние значения.
Ходы и подагенты
таймаут …s: команда прервана, вывод неполный. Причина: run упёрся в timeout_seconds (дефолт 120), код возврата 124 — обрыв, не падение. Что сделать: поднять timeout_seconds для вызова, раздробить команду или увести в фон; для всего инстанса — snens config timeout_seconds=<сек>.
пустой ответ модели дважды подряд (ход N, finish_reason=…). Причина: провайдер оборвал стрим или прислал вызов в непарсимом формате. Один пустой ответ ядро повторяет само, второй — ошибка: иначе прогон закрылся бы «успешно», ничего не сделав. Что сделать: проверить адрес, модель и ключ провайдера (snens providers), повторить запрос.
стрим молчит дольше N с после M символов. Причина: stream_idle_seconds (дефолт 120) — соединение живое, а данных нет. Что сделать: повторить; при повторе на одном провайдере — сменить его. Ключ stream_idle_seconds в config.toml.
agent wait: … ещё работает, истёк таймаут (код 3) / agent ask: … ответа нет. Причина: wait дождался своего таймаута, а Done в журнале ребёнка ещё нет; адресат не работает или не ответил, а контекста родителя он не видит. Что сделать: код 3 — не ошибка, звать wait снова или смотреть agent status <id>; при «ответа нет» — действовать самому.
Ядро и доступ
ядро не ответило / нет токена … (ядро запущено?). Причина: клиент не нашёл файл токена или до ядра не достучаться. Что сделать: systemctl --user status snens; snens tui-local работает без поднятой поверхности. Адрес задаётся --endpoint, файл токена — --token-file.
token file … must be private (chmod 600). Причина: файл токена читаем кем-то ещё либо в нём мусор — нужно минимум 32 символа без пробелов. Что сделать: chmod 600 api.token; побитый файл удалить, ядро создаст новый при старте, и старые клиенты после этого не пройдут авторизацию.
ядро слушает только loopback (сейчас --listen …). Причина: не-loopback адрес без явного разрешения, а единственная защита API — токен. Что сделать: --allow-remote для приватной сети (tailnet/WireGuard/LAN); публичный адрес требует ещё и --insecure-public, но лучше поставить TLS-прокси.
401 unauthorized после пейринга / код истёк / попытки исчерпаны. Причина: токен устройства отозван, клиент держит старый, либо код прожил свои 5 минут или сгорел после 5 неудачных попыток (он одноразовый). Что сделать: snens pair заново, новый код в экране подключения; подключённые устройства — snens clients.
sudo: действие не одобрено владельцем (или истёк срок ожидания). Причина: в headless-сессии действие ждёт кнопки в чате (approval_timeout_seconds, дефолт 300), её не нажали; либо очередь выключена нулём. Что сделать: нажать «разрешить» в клиенте или выполнить действие в snens tui-local, где пароль спрашивает askpass. Отказ брокера snens-priv не обходить: whitelist в /etc/snens-priv.conf расширяет человек.
Файлы и выкладка
Файл не находится после cd. Причина: cd внутри run переносится на следующие вызовы только при консервативном разборе — в начале команды или после ;, &&, ||, перевода строки, вне кавычек и $( ); cd без аргумента, cd - и подстановки переменных не отдаются. Что сделать: абсолютный путь, либо cwd у вызова, либо сменить каталог отдельной командой и проверить run pwd.
404 file not found / 403 file does not belong to this session. Причина: маршрут отдаёт файл только из каталогов этой сессии, чужой путь — 403. Что сделать: запрашивать path из parts записи лога; .. там не пройдёт.
409 session_owned при создании сессии. Причина: журнал держит другой процесс — два ядра на одном каталоге данных не работают, поверхность берёт эксклюзивный lock. Что сделать: одно ядро на каталог; второму инстансу — свои --data-dir и --config.
403 на установщик после выкладки. Причина: каталоги созданы с umask 077 → 0700, а раздающий сервис работает не под твоим пользователем; ни в логе сборки, ни в ls файлов этого не видно. Что сделать: каталоги 0755, файлы 0644 (find <каталог> -type d -exec chmod 0755 {} + и то же с 0644). Скрипт релиза делает это сам.