atomic-error-swallowing-frontend.md 5.1 KB

Подавление ошибок на фронтенде: пустой catch

Контекст: В нескольких компонентах фронтенда ошибки API и браузерных API подавляются пустым catch или callback-заглушкой. Это скрывает проблемы от пользователя и разработчика.

Проблемные места

1. Загрузка тегов и фич — PlaceForm.tsx

// PlaceForm.tsx:42-43 — ❌ пользователь не видит ошибку
useEffect(() => {
    api.get<Tag[]>('/tags').then(setTags).catch(() => {})       // подавлено
    api.get<Feature[]>('/features').then(setFeatures).catch(() => {})  // подавлено
}, [])

Последствия: Если API /tags или /features недоступен, форма рендерится без тегов/фич. Пользователь видит пустые секции и не понимает, почему.

2. Геолокация — MapView.tsx

// MapView.tsx:57-62 — ❌ пользователь отказал — молча
navigator.geolocation.getCurrentPosition(
    (pos) => provider.setCenter(pos.coords.latitude, pos.coords.longitude),
    () => {},  // ошибка подавлена
)

Последствия: Если пользователь запретил геолокацию, карта остаётся на Москве (default coordinates). Пользователь не понимает, почему карта не центрируется на нём.

3. WebSocket malformed message — useWebSocket.ts

// useWebSocket.ts:65 — ❌ malformed message логи не попадают
} catch { /* ignore malformed */ }

Последствия: Если сервер шлёт битые данные, разработчик не узнает об этом. Для resilience это ок, но должен быть debug-лог.

4. Logout API — useAuth.tsx

// useAuth.tsx:62-65 — ❌ ошибка logout скрыта
const logout = useCallback(async () => {
    try { await api.post('/auth/logout', {}) } catch {}  // подавлено
    setAccessToken(null)
    setUser(null)
}, [])

Последствия: Локальный logout происходит в любом случае (что правильно), но если сервер вернул ошибку, мы не узнаем. Админ не увидит, что сессия не была полностью завершена на сервере.

Когда подавление ошибок — это ок

Сценарий Статус Почему
WebSocket malformed message ✅ Приемлемо Resilience — не хотим падать при битых данных. Но нужен debug-лог.
Logout API error ✅ Приемлемо Force logout даже при недоступности сервера.
Загрузка тегов/фич ❌ Недопустимо UI становится неполным без явной индикации.
Геолокация отказана ❌ Недопустимо UX страдает — карта на неверном центре.

Решение

Для API запросов (PlaceForm):

useEffect(() => {
    api.get<Tag[]>('/tags')
        .then(setTags)
        .catch((err) => {
            console.error('Failed to load tags:', err)
            setTagsError('Не удалось загрузить теги')
        })
    api.get<Feature[]>('/features')
        .then(setFeatures)
        .catch((err) => {
            console.error('Failed to load features:', err)
            setFeaturesError('Не удалось загрузить характеристики')
        })
}, [])

И добавить состояние tagsError/featuresError для отображения пользователю.

Для геолокации (MapView):

navigator.geolocation.getCurrentPosition(
    (pos) => provider.setCenter(pos.coords.latitude, pos.coords.longitude),
    (err) => {
        console.warn('Geolocation denied or unavailable:', err.message)
        // Опционально: показать toast "Включите геолокацию для центрирования карты"
    },
)

Принцип

Подавляй ошибки только если:

  1. Приложение может корректно работать без этого действия
  2. Пользователь не заметит потери функциональности Иначе — хотя бы логируй и показывай пользователю.

Связанные заметки

  • [[architecture-overview]] — таблица P1
  • [[frontend-api-client]] — API клиент
  • [[MOC-backend-patterns]]

Источник

Code review PhotoPlaces 2026-06. PlaceForm.tsx:42-43, MapView.tsx:60, useWebSocket.ts:65, useAuth.tsx:63.

Теги

#frontend #error-handling #best-practice #ux