Голый int(cat_id)/int(total) в парсинге meta search_by_quarter падает на нечисловом NSPD-ответе и валит Phase 1 квартала #1574

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

Severity: medium · Категория: crash / устойчивость парсинга · Файл: backend/app/scrapers/nspd_bulk_client.py:342-346

backend/app/scrapers/nspd_bulk_client.py:342-346. В цикле сборки meta_counts конверсии meta_counts[int(cat_id)] = int(total) без try/except. Если NSPD вернёт totalCount/categoryId как нечисловую/float-строку ('20.0'→ValueError) или иной тип — int() кидает ValueError/TypeError. Это НЕ подкласс NspdBulkError, поэтому обёртка except NspdBulkError на :305 (404/400) его не ловит — пробрасывается из search_by_quarter. Caller harvest_quarter вызывает её bare await (bulk_harvest.py:130) без try/except → падает вся Phase 1 квартала: теряются уже распарсенные features и определение overflow-категорий (grid-walk Phase 2-3 не запустится). Противоречит защитному стилю: schemas/nspd_bulk.py:99-101 оборачивает int(val) в try/except с комментарием 'если NSPD когда-то вернёт string ID — мы не падаем'; list_objects_in_building (:578-587) тоже. ФИКС: обернуть конверсию в try/except (ValueError, TypeError) с logger.warning и skip элемента meta — по образцу _safe_int/schemas; не валить снапшот из-за одной битой записи meta.

Почему баг: Исключение здесь НЕ является подклассом NspdBulkError, поэтому обёртка 404/400 в search_by_quarter (строка 305 except NspdBulkError) его не ловит — оно пробрасывается из search_by_quarter, а harvest_quarter вызывает её bare await (bulk_harvest.py:130) без try/except → падает вся Phase 1 квартала: теряются и 20 уже распарсенных features, и определение overflow-категорий (grid-walk не запустится). Это прямое противоречие защитному стилю всего остального кода: schemas/nspd_bulk.py category_id оборачивает int() в try/except с комментарием «если NSPD когда-то вернёт string ID — мы не падаем», есть _safe_int, list_objects_in_building тоже оборачивает int(values[0]). Здесь же — единственное голое int() на горячем пути. Прошлый аудит этот участок пропустил.

Как чинить: Использовать defensive-конверсию: обернуть в try/except (ValueError, TypeError) с continue/skip битой записи meta, либо применить существующий _safe_int-подобный хелпер. Например: try: meta_counts[int(cat_id)] = int(total) except (ValueError, TypeError): logger.warning(...); continue.


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

**Severity:** medium · **Категория:** crash / устойчивость парсинга · **Файл:** `backend/app/scrapers/nspd_bulk_client.py:342-346` backend/app/scrapers/nspd_bulk_client.py:342-346. В цикле сборки meta_counts конверсии meta_counts[int(cat_id)] = int(total) без try/except. Если NSPD вернёт totalCount/categoryId как нечисловую/float-строку ('20.0'→ValueError) или иной тип — int() кидает ValueError/TypeError. Это НЕ подкласс NspdBulkError, поэтому обёртка except NspdBulkError на :305 (404/400) его не ловит — пробрасывается из search_by_quarter. Caller harvest_quarter вызывает её bare await (bulk_harvest.py:130) без try/except → падает вся Phase 1 квартала: теряются уже распарсенные features и определение overflow-категорий (grid-walk Phase 2-3 не запустится). Противоречит защитному стилю: schemas/nspd_bulk.py:99-101 оборачивает int(val) в try/except с комментарием 'если NSPD когда-то вернёт string ID — мы не падаем'; list_objects_in_building (:578-587) тоже. ФИКС: обернуть конверсию в try/except (ValueError, TypeError) с logger.warning и skip элемента meta — по образцу _safe_int/schemas; не валить снапшот из-за одной битой записи meta. **Почему баг:** Исключение здесь НЕ является подклассом NspdBulkError, поэтому обёртка 404/400 в search_by_quarter (строка 305 `except NspdBulkError`) его не ловит — оно пробрасывается из search_by_quarter, а harvest_quarter вызывает её bare await (bulk_harvest.py:130) без try/except → падает вся Phase 1 квартала: теряются и 20 уже распарсенных features, и определение overflow-категорий (grid-walk не запустится). Это прямое противоречие защитному стилю всего остального кода: schemas/nspd_bulk.py category_id оборачивает int() в try/except с комментарием «если NSPD когда-то вернёт string ID — мы не падаем», есть _safe_int, list_objects_in_building тоже оборачивает int(values[0]). Здесь же — единственное голое int() на горячем пути. Прошлый аудит этот участок пропустил. **Как чинить:** Использовать defensive-конверсию: обернуть в try/except (ValueError, TypeError) с continue/skip битой записи meta, либо применить существующий _safe_int-подобный хелпер. Например: try: meta_counts[int(cat_id)] = int(total) except (ValueError, TypeError): logger.warning(...); continue. --- <sub>deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.7 · unit B11</sub>
bot-backend added the
week ревью 1
label 2026-06-16 17:06:30 +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#1574
No description provided.