# Обработка ошибок

Обработка отсутствующих данных METAR и TAF в продакшне: семантика 404, фолбэки и ссылки на обработку ошибок платформы.



Кэширование и квоты: [Кэширование и мониторинг](/docs/v31/weather-integration-production).

**Ошибки платформы** (401, 403, 422, 429, 5xx, повторные попытки и экспоненциальная задержка (backoff), заголовки ограничения частоты запросов): [Обработка ошибок](/docs/errors).

**Примеры `404` для эндпоинтов:** [METAR](/docs/v31/weather-metar#error-responses) · [TAF](/docs/v31/weather-taf#error-responses) · [Ветер на высотах](/docs/v31/winds-aloft#error-responses).

### Когда погодные данные отсутствуют [#when-weather-data-is-missing]

Два разных случая `404` — одинаковый HTTP-статус и структура JSON (`{ "detail": "..." }`), но разный смысл:

**[METAR](https://en.wikipedia.org/wiki/METAR) 404.** Для этого ICAO нет станции метеонаблюдений. Типично для частных площадок, многих военных аэродромов и некоторых международных аэропортов, которые не передают данные в сеть ASOS/AWOS. Аэропорт при этом может существовать — он просто не публикует [сводки METAR](https://en.wikipedia.org/wiki/METAR). Показывайте **Погода недоступна** и, если это уместно, позвольте пользователю продолжить.

**[TAF](https://en.wikipedia.org/wiki/Terminal_aerodrome_forecast) 404.** У аэропорта может быть [METAR](https://en.wikipedia.org/wiki/METAR), но [TAF](https://en.wikipedia.org/wiki/Terminal_aerodrome_forecast) для него не выпускается. Небольшие аэропорты без значительного трафика по приборам часто имеют только [METAR](https://en.wikipedia.org/wiki/METAR). Запрашивайте [METAR](https://en.wikipedia.org/wiki/METAR) как обычно, пропускайте [TAF](https://en.wikipedia.org/wiki/Terminal_aerodrome_forecast) и показывайте только текущие условия.

```python
import requests

HEADERS = {
    "X-RapidAPI-Key": "YOUR_RAPIDAPI_KEY",
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"


def get_weather(icao: str) -> dict:
    """
    Returns a dict with 'metar' and 'taf' keys.
    Either can be None if data is unavailable for this airport.
    """
    result = {"metar": None, "taf": None}

    r = requests.get(f"{BASE}/weather/metar/{icao}", headers=HEADERS, params={"parsed": "true"}, timeout=(10, 15))
    if r.status_code == 200:
        result["metar"] = r.json()
    elif r.status_code != 404:
        r.raise_for_status()

    r = requests.get(f"{BASE}/weather/taf/{icao}", headers=HEADERS, params={"parsed": "true"}, timeout=(10, 15))
    if r.status_code == 200:
        result["taf"] = r.json()
    elif r.status_code != 404:
        r.raise_for_status()

    return result


# weather = get_weather("KOXB")  # small airport, no TAF
# print("METAR:", "available" if weather["metar"] else "not available")
# print("TAF:",   "available" if weather["taf"]   else "not available")
```

Отображайте доступные данные [METAR](https://en.wikipedia.org/wiki/METAR)/[TAF](https://en.wikipedia.org/wiki/Terminal_aerodrome_forecast) и явно помечайте пробелы (например, «Для этого аэропорта прогноза нет»). Погодный `404` означает, что **продукт не публикуется** для этого ICAO, а не ошибку на стороне клиента.

Для временных сбоев (`429`, `5xx`) используйте вспомогательную функцию повторных попыток со страницы [Обработка ошибок](/docs/errors#retry-rules).

### Эндпоинты на маршруте (bbox) [#en-route-endpoints-bbox]

[Ветер на высотах](/docs/v31/winds-aloft), [PIREP](/docs/v31/pireps) и [AIRMET/SIGMET](/docs/v31/airsigmet) используют query-параметр `bbox`, а не один код ICAO. Семантика ошибок отличается от [METAR](https://en.wikipedia.org/wiki/METAR)/[TAF](https://en.wikipedia.org/wiki/Terminal_aerodrome_forecast):

| Эндпоинт             | Пустой результат          | `404`                             | Примечания                                                    |
| -------------------- | ------------------------- | --------------------------------- | ------------------------------------------------------------- |
| **Ветер на высотах** | -                         | В bbox нет станций FB             | Покрытие только США — расширьте bbox или проверьте координаты |
| **PIREP**            | `reports: []`, `total: 0` | - (при некорректном bbox — `400`) | Нет свежих донесений пилотов — это **не** ошибка              |
| **AIRMET/SIGMET**    | `reports: []`, `total: 0` | - (при некорректном bbox — `400`) | Нет активных предупреждений — обычное дело в погоду VFR       |

```python
import requests

HEADERS = {
    "X-RapidAPI-Key": "YOUR_RAPIDAPI_KEY",
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
BBOX = "39,-80,42,-73"  # example corridor


def enroute_weather(bbox: str) -> dict:
    """Fetch en-route layers. Empty lists are valid - do not treat as failures."""
    out = {"winds": None, "pireps": [], "airsigmets": []}

    r = requests.get(
        f"{BASE}/weather/winds-aloft",
        headers=HEADERS,
        params={"bbox": bbox, "forecast": 12, "level": "low"},
        timeout=(10, 20),
    )
    if r.status_code == 200:
        out["winds"] = r.json()
    elif r.status_code != 404:
        r.raise_for_status()

    r = requests.get(
        f"{BASE}/weather/pireps",
        headers=HEADERS,
        params={"bbox": bbox, "hours": 3},
        timeout=(10, 20),
    )
    r.raise_for_status()
    out["pireps"] = r.json().get("reports") or []

    r = requests.get(
        f"{BASE}/weather/airsigmet",
        headers=HEADERS,
        params={"bbox": bbox, "type": "airmet"},
        timeout=(10, 25),
    )
    r.raise_for_status()
    out["airsigmets"] = r.json().get("reports") or []

    return out


# wx = enroute_weather(BBOX)
# print("Winds stations:", wx["winds"]["total"] if wx["winds"] else "none in bbox")
# print("PIREPs:", len(wx["pireps"]))
# print("AIRMETs:", len(wx["airsigmets"]))
```

Показывайте в интерфейсе явные пустые состояния («Нет донесений пилотов за последние 3 ч», «Нет активных [AIRMET](https://www.aviationweather.gov/help/data/#airmet)») вместо баннеров с ошибкой.

***

См. также: [METAR](/docs/v31/weather-metar) · [TAF](/docs/v31/weather-taf) · [Ветер на высотах](/docs/v31/winds-aloft) · [PIREP](/docs/v31/pireps) · [AIRMET/SIGMET](/docs/v31/airsigmet) · [Паттерны для продакшна](/docs/v31/weather-integration-production) · [Сценарии для аэропорта](/docs/v31/weather-integration-airport) · [Сценарии на маршруте](/docs/v31/weather-integration-enroute)
