[Fable 5][P3] Крах weekly POI-синка 29 февраля: date.replace(year=-2) бросает ValueError #1232

Closed
opened 2026-06-13 04:49:47 +00:00 by bot-backend · 0 comments
Collaborator

Из армейского ревью Claude Fable 5 (2026-06-11)

Confirmed by 2/2 адверсариальных верификатора, severity P3 (correctness), confidence 0.7.

Файл

backend/app/services/site_finder/poi_loader.py:113

Evidence (цитата кода)

    two_years_ago = date.today().replace(year=date.today().year - 2)

Why bug

При запуске sync_poi_to_db 29 февраля (напр. 2028-02-29) date(2028,2,29).replace(year=2026) бросает ValueError: day is out of range for month — задача падает сразу после полного обхода Overpass (14 запросов), ни одна строка не апсертится, недельный прогон POI потерян.

Suggested fix

Заменить на date.today() - timedelta(days=730) (или try/except с fallback на day=28).

Verify notes

  • [real/P3] Подтверждено трассировкой: poi_loader.py:112 завершает полный Overpass-обход, затем :113 на 29 февраля бросает ValueError (проверено: leap−2 никогда не leap, краш детерминирован). Таск poi_sync.py re-raise без retry — 0 апсертов, недельный синк потерян. Нюанс: cron '0 3 * * mon' попадёт на 29.02 лишь в 2044 (2028-02-29 — вторник); ручной запуск падает в любое 29.02. P3 адекватно: редко, самолечится через неделю, ошибка логируется.
  • [real/P3] Подтверждено: год-2 от високосного никогда не високосный, поэтому 29 февраля replace(year-2) детерминированно бросает ValueError (проверено). Guard'ов нет: try начинается со стр. 121, fetch_overpass (стр. 112) уже выполнен — 14 запросов впустую, upsert не стартует; Celery-обёртка логирует и re-raise без retry — прогон потерян. Защита частичная: beat = пн 03:00 (ближайший пн 29.02 — 2044), но admin_scrape.py:419 запускает таску любым днём (напр. 29.02.2028). Редко, самолечится через неделю — P3.

Provenance

  • Finders: site-finder-B
  • Confidence: 0.7
  • Originally batched at: main@d796027
## Из армейского ревью Claude Fable 5 (2026-06-11) Confirmed by 2/2 адверсариальных верификатора, severity **P3** (correctness), confidence 0.7. ## Файл [`backend/app/services/site_finder/poi_loader.py:113`](backend/app/services/site_finder/poi_loader.py:113) ## Evidence (цитата кода) ``` two_years_ago = date.today().replace(year=date.today().year - 2) ``` ## Why bug При запуске sync_poi_to_db 29 февраля (напр. 2028-02-29) date(2028,2,29).replace(year=2026) бросает ValueError: day is out of range for month — задача падает сразу после полного обхода Overpass (14 запросов), ни одна строка не апсертится, недельный прогон POI потерян. ## Suggested fix Заменить на `date.today() - timedelta(days=730)` (или try/except с fallback на day=28). ## Verify notes - [real/P3] Подтверждено трассировкой: poi_loader.py:112 завершает полный Overpass-обход, затем :113 на 29 февраля бросает ValueError (проверено: leap−2 никогда не leap, краш детерминирован). Таск poi_sync.py re-raise без retry — 0 апсертов, недельный синк потерян. Нюанс: cron '0 3 * * mon' попадёт на 29.02 лишь в 2044 (2028-02-29 — вторник); ручной запуск падает в любое 29.02. P3 адекватно: редко, самолечится через неделю, ошибка логируется. - [real/P3] Подтверждено: год-2 от високосного никогда не високосный, поэтому 29 февраля replace(year-2) детерминированно бросает ValueError (проверено). Guard'ов нет: try начинается со стр. 121, fetch_overpass (стр. 112) уже выполнен — 14 запросов впустую, upsert не стартует; Celery-обёртка логирует и re-raise без retry — прогон потерян. Защита частичная: beat = пн 03:00 (ближайший пн 29.02 — 2044), но admin_scrape.py:419 запускает таску любым днём (напр. 29.02.2028). Редко, самолечится через неделю — P3. ## Provenance - Finders: `site-finder-B` - Confidence: 0.7 - Originally batched at: main@d796027
bot-backend added the
Fable 5 ревью
label 2026-06-13 04:49:47 +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#1232
No description provided.