Fix boot race: retry on any startup error and clean up paho threads - #462
Closed
tomer-w wants to merge 2 commits into
Closed
Fix boot race: retry on any startup error and clean up paho threads#462tomer-w wants to merge 2 commits into
tomer-w wants to merge 2 commits into
Conversation
… fails When the MQTT broker restarts (e.g. Victron power cycle, power outage), paho-mqtt auto-reconnects and fires the on_connect callback. Previously, if _setup_subscriptions() raised ANY exception during reconnection, the _on_connect handler called client.disconnect(), which permanently killed paho's auto-reconnect mechanism. The integration would never recover without a manual reload. Changes: - Only call client.disconnect() on first-connect errors (auth failures, connection refused). On reconnection, log the error and let paho continue auto-reconnecting. - Track subscription state with _subscribed flag, cleared on disconnect. - Retry failed subscriptions from the keepalive loop (runs every 30s), so even if subscription setup fails during reconnection, it will be retried automatically. - Add reconnection-specific logging (session_present flag, retry status) for better diagnostics. Closes #461 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6374e2f1-1fb3-453d-a1c2-dddf69a62f61
When HA and Victron boot simultaneously (power outage, no UPS), the integration can fail permanently because: 1. Hub.start() only catches CannotConnectError, but connect() can also raise NotConnectedError (if connection drops mid-setup) or other exceptions. Uncaught exceptions cause HA to treat the failure as permanent (no retry). Fix: catch Exception (except AuthenticationError) and convert to ConfigEntryNotReady so HA retries with backoff. 2. connect() calls loop_start() early, creating a paho background thread. If any later step fails, loop_stop() is never called, leaking the thread. Each HA retry leaks another thread. Fix: try/except around post-loop_start() code that calls loop_stop() on failure. 3. disconnect() calls client.disconnect() but not loop_stop(), so the background thread is never explicitly stopped. Fix: add loop_stop(). Fixes #461 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6374e2f1-1fb3-453d-a1c2-dddf69a62f61
tomer-w
force-pushed
the
tomer-w-fix-mqtt-reconnect-resubscribe
branch
from
July 15, 2026 05:49
0df6a30 to
fbdd541
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Fixes #461
When HA and the Victron system boot simultaneously after a power outage (no UPS), the integration can fail permanently and never recover until manually reloaded.
Root Cause
Hub.start()only catchesCannotConnectErrorandAuthenticationError. But during the boot race,connect()can raise other exceptions (e.g.NotConnectedErrorif the connection drops mid-setup, orAssertionError, etc.). Any uncaught exception causes HA to treat the failure as permanent — no retry.Additionally,
connect()starts a paho background thread vialoop_start()early in the setup. If any later step fails, the thread is leaked (noloop_stop()call). Each HA retry creates a new Hub, leaking another thread.Fix (3 minimal changes)
Hub.start():except CannotConnectError→except Exception— any startup error (except auth) becomesConfigEntryNotReady, so HA retries with exponential backoffconnect(): Wrap post-loop_start()code in try/except that callsloop_stop()on failure — prevents leaked paho threads on retrydisconnect(): Addloop_stop()— properly stops the background thread