weather_cache._fetch_seasonal_remote: ZeroDivisionError/ValueError при пустых t_min/precip и непустом t_max (раздельные None-guard'ы) #1578

Closed
opened 2026-06-16 17:08:07 +00:00 by bot-backend · 0 comments
Collaborator

Severity: low · Категория: edge-case / div-by-zero · Файл: backend/app/services/weather_cache.py:216-237

Файл: backend/app/services/weather_cache.py:212-237.

Суть: накопление в бакеты идёт тремя НЕЗАВИСИМЫМИ условиями — t_max при t_max[i] is not None (216-217), t_min отдельно (218-219), precip отдельно (220-221). Списки внутри сезона могут иметь разную длину; vals['t_min']/vals['precip'] могут быть ПУСТЫМИ при непустом vals['t_max']. Гейт проверяет ТОЛЬКО t_max: if not vals['t_max'] (226). Далее безусловно: sum(vals['t_min'])/len(vals['t_min']) (231), min(vals['t_min']) (233), sum(vals['precip'])/len(vals['precip']) (234).

Импакт: если источник (MRI-AGCM3-2-S) для всех дней сезона заполнил t_max, но t_min или precip = null, то len(...) == 0 -> ZeroDivisionError (или min([]) -> ValueError). Ловится широким except (245-247) -> весь сезонный ответ молча -> None, negative-cache 300с. Граничный сценарий, severity low.

Фикс: считать каждую метрику только при непустоте её собственного списка (... if vals['t_min'] else None и т.п.), либо расширить гейт 226 на все три списка.

Почему баг: Если в источнике (MRI-AGCM3-2-S) для всех дней сезона t_max заполнен, а t_min или precip = null, len(...) == 0 → ZeroDivisionError. Ловится широким except (245-247) → весь сезонный ответ молча превращается в None и negative-кэшируется на 5 минут. Тихая потеря климатических нормалей для точки. Граничный, но реальный сценарий из-за рассинхрона null-флагов между метриками.

Как чинить: Гейтить каждую метрику отдельно (avg_t_min только если vals['t_min'], avg_precip только если vals['precip'], иначе None), либо синхронно накапливать все три значения дня только когда t_max И t_min И precip не None.


deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.8 · unit B13

**Severity:** low · **Категория:** edge-case / div-by-zero · **Файл:** `backend/app/services/weather_cache.py:216-237` Файл: backend/app/services/weather_cache.py:212-237. Суть: накопление в бакеты идёт тремя НЕЗАВИСИМЫМИ условиями — t_max при `t_max[i] is not None` (216-217), t_min отдельно (218-219), precip отдельно (220-221). Списки внутри сезона могут иметь разную длину; vals['t_min']/vals['precip'] могут быть ПУСТЫМИ при непустом vals['t_max']. Гейт проверяет ТОЛЬКО t_max: `if not vals['t_max']` (226). Далее безусловно: `sum(vals['t_min'])/len(vals['t_min'])` (231), `min(vals['t_min'])` (233), `sum(vals['precip'])/len(vals['precip'])` (234). Импакт: если источник (MRI-AGCM3-2-S) для всех дней сезона заполнил t_max, но t_min или precip = null, то len(...) == 0 -> ZeroDivisionError (или min([]) -> ValueError). Ловится широким except (245-247) -> весь сезонный ответ молча -> None, negative-cache 300с. Граничный сценарий, severity low. Фикс: считать каждую метрику только при непустоте её собственного списка (`... if vals['t_min'] else None` и т.п.), либо расширить гейт 226 на все три списка. **Почему баг:** Если в источнике (MRI-AGCM3-2-S) для всех дней сезона t_max заполнен, а t_min или precip = null, len(...) == 0 → ZeroDivisionError. Ловится широким except (245-247) → весь сезонный ответ молча превращается в None и negative-кэшируется на 5 минут. Тихая потеря климатических нормалей для точки. Граничный, но реальный сценарий из-за рассинхрона null-флагов между метриками. **Как чинить:** Гейтить каждую метрику отдельно (avg_t_min только если vals['t_min'], avg_precip только если vals['precip'], иначе None), либо синхронно накапливать все три значения дня только когда t_max И t_min И precip не None. --- <sub>deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.8 · unit B13</sub>
bot-backend added the
week ревью 1
label 2026-06-16 17:08:07 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1578
No description provided.