From 9d898f4277cb71ad40b1bf9b3b68add0a08b9523 Mon Sep 17 00:00:00 2001 From: 1sakshm Date: Sun, 25 Oct 2026 04:39:45 +0530 Subject: [PATCH] Return 502 when Open-Meteo fails in the weather forecast endpoint Upstream failures from openmeteo_requests (HTTP errors, rate limits, no network) are now reported as 502 WEATHER_FETCH_FAILED instead of 500 INTERNAL_ERROR. Fixes #742 --- app/api/routes/weather.py | 4 ++++ tests/test_api.py | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/app/api/routes/weather.py b/app/api/routes/weather.py index f1e7980..d696e87 100644 --- a/app/api/routes/weather.py +++ b/app/api/routes/weather.py @@ -2,6 +2,7 @@ from fastapi import APIRouter, Query from fastapi.exceptions import RequestValidationError +from openmeteo_requests.Client import OpenMeteoRequestsError from app.core.errors.base import AppError from app.services.external_apis.weather_api import WeatherAPI @@ -55,5 +56,8 @@ def get_weather_forecast( latitude, longitude, start_date.isoformat(), end_date.isoformat(), hourly_fields=requested ) return weather_data + except OpenMeteoRequestsError as e: + # Open-Meteo failed or was unreachable: the failure is upstream, not ours + raise AppError(str(e), status_code=502, error_code="WEATHER_FETCH_FAILED") except Exception as e: raise AppError(str(e), status_code=500) \ No newline at end of file diff --git a/tests/test_api.py b/tests/test_api.py index 3088215..88578f4 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -614,6 +614,29 @@ def fake_get_weather(self, latitude, longitude, start_date, end_date, hourly_fie "end_date": "2026-10-20", } + def test_forecast_upstream_error_is_502(self, client, monkeypatch): + from openmeteo_requests.Client import OpenMeteoRequestsError + + def fake_weather_api(*args, **kwargs): + raise OpenMeteoRequestsError("failed to request 'https://api.open-meteo.com/v1/forecast': offline") + + monkeypatch.setattr("openmeteo_requests.Client.weather_api", fake_weather_api) + + resp = client.get(self.WEATHER_URL, params=self.VALID) + assert resp.status_code == 502 + body = resp.json() + assert body["error_code"] == "WEATHER_FETCH_FAILED" + assert "offline" in body["message"] + + def test_forecast_unexpected_error_is_500(self, client, monkeypatch): + def fake_get_weather(*args, **kwargs): + raise ValueError("boom") + + monkeypatch.setattr("app.api.routes.weather.WeatherAPI.get_weather", fake_get_weather) + + resp = client.get(self.WEATHER_URL, params=self.VALID) + assert resp.status_code == 500 + @pytest.mark.parametrize( "overrides, field", [