atomic-sentinel-error-handler-mapping.md 1.8 KB

Sentinel-ошибку мало объявить — её нужно смапить в хендлере

Контекст: В services/places.go корректно объявлен sentinel ErrNotYourPlace и возвращается через %w. Но хендлер PlaceHandler.Update мапил любую ошибку Update в 500 internal server error. В итоге чужой пользователь при PATCH /places/{id} получал 500 вместо 403.

Суть: Sentinel-error даёт пользу только если вызывающий слой действительно делает errors.Is. Объявление ошибки и её маппинг в HTTP-статус — две разные обязанности; пропуск второй превращает ожидаемую бизнес-ситуацию (нет прав) в «внутреннюю ошибку» и засоряет логи 500-ками.

Решение:

place, err := h.placeSvc.Update(r.Context(), input, isModerator)
if err != nil {
    if errors.Is(err, services.ErrNotYourPlace) {
        writeError(w, http.StatusForbidden, "not your place", nil)
        return
    }
    writeError(w, http.StatusInternalServerError, "failed to update place", err)
    return
}

Правило: при добавлении sentinel-ошибки сразу проверь все хендлеры, которые её могут получить — на каждый осмысленный sentinel должен быть свой статус (403/404/409), а не общий 500.

Связанные заметки: [[atomic-sentinel-errors-go]], [[backend-auth-security]] Источник: Code review 2026-06-30 (neyrogovnarik), P1 fix в handlers/places.go

#golang #backend #error-handling #http #bug