Skip to content

forecastsolar: wrap HA-ML WebSocket failures as ProviderError - #414

Merged
MaStr merged 2 commits into
mainfrom
claude/pr-408-forecast-provider-bug-1xbjrr
Aug 13, 2026
Merged

forecastsolar: wrap HA-ML WebSocket failures as ProviderError#414
MaStr merged 2 commits into
mainfrom
claude/pr-408-forecast-provider-bug-1xbjrr

Conversation

@MaStr

@MaStr MaStr commented Aug 13, 2026

Copy link
Copy Markdown
Owner

ForecastSolarHomeAssistantML.get_raw_data_from_provider() let DNS,
connection, and auth failures from the WebSocket client escape
unwrapped. ForecastSolarBaseclass.refresh_data() only catches
(ConnectionError, TimeoutError, ProviderError), so these exceptions
bypassed the cache fallback entirely (same class of bug as #408 in
FCSolar, but for the websockets-based HA-ML provider).

Wrap OSError, WebSocketException, and RuntimeError from the fetch as
ProviderError so cached forecast data remains usable until its TTL
expires.

ForecastSolarHomeAssistantML.get_raw_data_from_provider() let DNS,
connection, and auth failures from the WebSocket client escape
unwrapped. ForecastSolarBaseclass.refresh_data() only catches
(ConnectionError, TimeoutError, ProviderError), so these exceptions
bypassed the cache fallback entirely (same class of bug as #408 in
FCSolar, but for the websockets-based HA-ML provider).

Wrap OSError, WebSocketException, and RuntimeError from the fetch as
ProviderError so cached forecast data remains usable until its TTL
expires.
Copilot AI lite review requested due to automatic review settings August 13, 2026 05:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves reliability of the Home Assistant ML solar forecast provider by ensuring WebSocket DNS/connection/auth failures are surfaced as ProviderError, allowing ForecastSolarBaseclass.refresh_data() to fall back to cached raw data until TTL expiry.

Changes:

  • Wrap OSError, WebSocketException, and RuntimeError from the HA-ML WebSocket fetch path as ProviderError.
  • Add regression tests covering DNS failure, WebSocket failure, auth failure, and cache fallback behavior on connection failure.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tests/test_forecast_solar_homeassistant_ml.py Adds regression tests asserting network/auth failures are wrapped and cache fallback remains effective.
src/batcontrol/forecastsolar/forecast_homeassistant_ml.py Wraps WebSocket-related failures as ProviderError so baseclass error handling can use cached data.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/batcontrol/forecastsolar/forecast_homeassistant_ml.py Outdated
Chain ProviderError from the original exception and log with a stack
trace instead of discarding it via 'from None'. Unlike the fcsolar.py
case this wraps, none of OSError/WebSocketException/RuntimeError here
can carry the API token (it is sent as a post-connect JSON payload,
never part of the URL or handshake), so there is no leak risk in
keeping the original error for diagnostics.

Addresses review feedback on PR #414.
Copilot AI review requested due to automatic review settings August 13, 2026 19:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/batcontrol/forecastsolar/forecast_homeassistant_ml.py:344

  • Catching RuntimeError here also wraps the "event loop is already running" error from run_until_complete(). That turns a programming/usage error into a ProviderError, which can silently trigger cache fallback and make the underlying issue hard to diagnose. Guard against a running loop before calling run_until_complete (or avoid wrapping that specific RuntimeError).
        try:
            loop = asyncio.get_event_loop()
        except RuntimeError:
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)

        try:
            return loop.run_until_complete(self._fetch_entity_state_async())
        except (OSError, WebSocketException, RuntimeError) as e:
            logger.error(
                'HomeAssistant WebSocket request failed for entity %s: %s',
                self.entity_id, e, exc_info=True)
            raise ProviderError(
                f'HomeAssistant WebSocket request failed for entity {self.entity_id}: {e}'
            ) from e

@MaStr
MaStr merged commit b253ecc into main Aug 13, 2026
14 checks passed
@MaStr
MaStr deleted the claude/pr-408-forecast-provider-bug-1xbjrr branch August 13, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants