# Ошибки - Только стандартный `errors` + `fmt.Errorf`. Сторонних пакетов ошибок нет: контекст несёт `slog`, стек-трейсы для домашнего сервиса избыточны. - Контекст добавляем обёрткой `%w` — это дефолт, чтобы `errors.Is`/`As` работали сквозь слои. `%v` — только когда причину сознательно не раскрываем. - Стиль сообщения: со строчной, без точки, без «failed to». Контекст — операция или субъект (`"open archive: %w"`), каждый слой добавляет **свой** смысл, не повторяя нижний. - Граничные ошибки транслируем в доменные у источника: `sql.ErrNoRows` → `store.ErrNotFound` внутри `store`, чтобы выше не торчал `database/sql`. - **Sentinel** (`var ErrNotFound = errors.New(...)`) — для условий, на которые ветвится код. **Типизированная ошибка** — когда вызывающему нужны данные ошибки. Не плодим типы там, где хватает sentinel. - Наружу (HTTP) отдаём человекочитаемое сообщение по доменной ошибке, не сырой `err.Error()`. Маппинг доменная ошибка → статус живёт в одной точке в `httpapi`; новая штатная ветвь отказа заводится sentinel'ом и добавляется туда, иначе `default` отдаст 500 на нормальный конфликт. - Собрать независимые ошибки (валидация конфига — все проблемы разом) — `errors.Join`. - `panic` — только невосстановимое: нарушенный инвариант, сбой инициализации. `recover` — на верхней границе HTTP-обработчика. - Глушить ошибку без лога — только с однострочным комментарием «почему».