# Frontend: обработка ошибок

Цель: предсказуемое поведение UI при ошибках сети/валидации/доступа без утечки внутренних деталей.

## Модель ошибок на фронте
Правило: UI работает с нормализованной ошибкой, а не с “сырым” `AxiosError`.

Рекомендуемый минимум полей (пример):
- `kind`: `network` | `timeout` | `canceled` | `http`
- `status`: HTTP status (если есть)
- `code`: стабильный код (если есть/принят)
- `messageKey`: i18n ключ для показа пользователю
- `field`: имя поля (для ошибок валидации, если применимо)
- `traceId`/`requestId`: если приходит от backend и можно показать в “подробностях”/копировании

## Где обрабатывать
- Нормализация ошибок: в `src/shared/api/errors.ts`.
- Решение “что показать пользователю”: на уровне фичи/страницы (она знает контекст UX).
- Глобальная обработка:
  - 401/403: централизованная реакция (например, редирект на логин/экран “нет доступа”) через router/store;
  - оффлайн: единый баннер/экран деградации;
  - отмена запросов: не считать ошибкой UI (не показывать toast).

## Что запрещено
- показывать пользователю сырые сообщения backend (`err.message`, stacktrace, SQL и т.п.);
- логировать/собирать в аналитику чувствительные данные/PII;
- делать “глобальный toast на любую ошибку” без контекста (шум и плохой UX).

## Стратегии UX
- Validation (400): подсветка конкретных полей + локальное сообщение (через `messageKey` + `field`).
- NotFound (404): пустое состояние/страница “не найдено” (по месту).
- Conflict (409): объяснимое сообщение и действие (повторить/обновить/перейти).
- 5xx/Unavailable: сообщение о временной проблеме + “повторить”.
- Timeout/Network: “проверьте соединение” + “повторить”; при оффлайне — единая деградация.

## WebSocket (если используется)
- Ошибки соединения (disconnect/reconnect) не должны превращаться в “спам toasts”; показываем статус соединения и даём понятное действие (например, “переподключить”).
- Не показывать пользователю “сырые” причины закрытия; только безопасные i18n сообщения.
