# Fehlerbehandlung

Fehler bei Luftfahrzeug- und ADS-B-Daten im Produktivbetrieb behandeln — fehlende Kennzeichen, leere Filter und Wiederholungsversuche.



Caching und Monitoring: [Caching & Monitoring](/docs/v31/aircraft-adsb-integration-production).

**Plattformfehler** (401, 403, 422, 429, 5xx, Wiederholungsversuche/Backoff, Rate-Limit-Header): [Fehlerbehandlung](/docs/errors).

### Luftfahrzeugabfrage: `found` ist kein 404 [#aircraft-lookup-found-is-not-a-404]

Der Endpoint für Kennzeichen gibt immer `200` zurück, wenn die Anfrage selbst gültig ist — auch dann, wenn das Kennzeichen nicht im Luftfahrzeugregister von SkyLink enthalten ist. Behandeln Sie ein fehlendes Luftfahrzeug nicht als HTTP-Fehler.

| Situation                | HTTP-Status | Erkennung       |
| ------------------------ | ----------- | --------------- |
| Kennzeichen bekannt      | `200`       | `found: true`   |
| Kennzeichen unbekannt    | `200`       | `found: false`  |
| Fehlerhaftes Pfadsegment | `404`       | HTTP-Statuscode |

Prüfen Sie immer `found`, bevor Sie `aircraft.*`-Felder lesen. Das Lesen von `aircraft.icao_type` in einer Antwort mit `found: false` löst einen `KeyError` aus.

### Flugleistungsdaten: 422 bei unbekanntem Typ [#aircraft-performance-422-on-unknown-type]

`GET /aircraft/performance/{icao_type}` gibt `422` zurück, wenn der ICAO-Typcode nicht erkannt wird. Das ist ein normales Ergebnis, wenn Sie an eine Registerabfrage anknüpfen: Nicht jeder `icao_type`-Wert im Register hat einen entsprechenden Leistungsdatensatz.

| Antwort | Bedeutung                                                             |
| ------- | --------------------------------------------------------------------- |
| `200`   | Leistungsdaten zurückgegeben                                          |
| `422`   | Typcode nicht in der Leistungsdatenbank — mit Fallback weiterarbeiten |

### Live-ADS-B: leeres `aircraft[]` ist kein Fehler [#live-ads-b-empty-aircraft-is-not-an-error]

`GET /adsb/aircraft` gibt `200` mit `aircraft: []` zurück, wenn kein Luftfahrzeug dem angefragten Filter (Radius, Bbox oder Rufzeichen) entspricht. Das ist ein gültiges leeres Ergebnis — zeigen Sie kein Fehlerbanner an. Der Feed ist live; Luftfahrzeuge bewegen sich innerhalb von Sekunden in Ihren Filterbereich hinein und wieder heraus.

Außerdem gilt: **Cachen Sie niemals Live-[ADS-B](https://www.faa.gov/air_traffic/technology/adsb)-Antworten**. Der Feed wird alle paar Sekunden aktualisiert; eine gecachte Position ist bereits veraltet, wenn das nächste Rendering erfolgt.

### Historische ADS-B-Daten: Tarifbeschränkungen und Zeitraumfehler [#historical-ads-b-plan-gating-and-window-errors]

Die `/ultra/history/...`-Endpoints erfordern den Tarif Pro oder höher. Eine Antwort mit `401` oder `403` enthält einen `message`-Schlüssel, der die Einschränkung erklärt — zeigen Sie diese Meldung an statt eines allgemeinen Textes wie „Zugriff verweigert“.

Der Endpoint `/ultra/history/airport/{icao}/traffic` erfordert den korrekten `direction`-Wert:

| Korrekt         | Falsch                 |
| --------------- | ---------------------- |
| `direction=arr` | `direction=arrivals`   |
| `direction=dep` | `direction=departures` |

Der Such-Endpoint `/ultra/history/flights` gibt `422` zurück, wenn der angefragte Zeitraum die maximale Aufbewahrungsdauer des Pfads überschreitet (90 Tage bei `/ultra/...`). Verkleinern Sie den Zeitraum und versuchen Sie es erneut.

```python
import os
import requests

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


def lookup_registration(registration: str) -> dict | None:
    """
    Returns aircraft dict or None when not found.
    Always checks the `found` field — never treats found=false as an error.
    """
    r = requests.get(
        f"{BASE}/aircraft/registration/{registration}",
        headers=HEADERS,
        timeout=(10, 15),
    )
    r.raise_for_status()
    data = r.json()
    if not data.get("found"):
        print(f"Registration {registration} not in registry (found=false).")
        return None
    return data["aircraft"]


def fetch_performance(icao_type: str) -> dict | None:
    """
    Returns performance data or None on 422 (type not in database).
    """
    r = requests.get(
        f"{BASE}/aircraft/performance/{icao_type}",
        headers=HEADERS,
        timeout=(10, 15),
    )
    if r.status_code == 422:
        print(f"Performance data not available for type {icao_type!r} (422).")
        return None
    r.raise_for_status()
    return r.json()


def fetch_history_with_plan_gate(registration: str) -> list[dict] | None:
    """
    Fetches recent historical flights. Surfaces the plan gate message on 401/403.
    """
    r = requests.get(
        f"{BASE}/ultra/history/flights",
        headers=HEADERS,
        params={"registration": registration, "limit": 5},
        timeout=(10, 25),
    )
    if r.status_code in (401, 403):
        msg = r.json().get("message", "Plan not entitled.")
        print(f"Access denied: {msg}")
        print("Upgrade to Pro or above for /ultra/history/... endpoints.")
        return None
    r.raise_for_status()
    return r.json().get("flights", [])


def main() -> None:
    # 1. Registration lookup — check found field
    ac = lookup_registration("N636JB")
    if ac:
        print(f"Found: {ac['registration']} / {ac['icao_type']} / {ac['owner_operator']}")
        # 2. Chain to performance — handle 422
        perf = fetch_performance(ac["icao_type"])
        if perf:
            print(f"Cruise speed: {perf.get('cruise_speed_ktas')} kt")
        else:
            print("Showing registration data only — no performance record.")
    else:
        print("Show empty state to user — aircraft not in registry.")

    # 3. Historical search — handle 401/403 plan gate
    flights = fetch_history_with_plan_gate("N636JB")
    if flights is not None:
        print(f"Last {len(flights)} archived flights retrieved.")


if __name__ == "__main__":
    main()
```

Für Antworten mit `429` und `5xx` verwenden Sie die Hilfsfunktion für Wiederholungsversuche unter [Fehlerbehandlung](/docs/errors#retry-rules).

***

Siehe auch: [Luftfahrzeugabfrage](/docs/v31/aircraft-lookup) · [Flugleistungsdaten](/docs/v31/aircraft-performance) · [ADS-B](/docs/v31/adsb) · [Historische ADS-B-Daten](/docs/v31/historical-adsb) · [Muster für den Produktivbetrieb](/docs/v31/aircraft-adsb-integration-production)
