Skip to content

fix(ha-api): an unreachable Home Assistant no longer aborts startup - #46

Merged
cayossarian merged 2 commits into
mainfrom
fix/ha-validate-survives-timeout
Aug 28, 2026
Merged

fix(ha-api): an unreachable Home Assistant no longer aborts startup#46
cayossarian merged 2 commits into
mainfrom
fix/ha-validate-survives-timeout

Conversation

@cayossarian

Copy link
Copy Markdown
Member

What

HAClient.async_validate sets aiohttp.ClientTimeout(total=_TIMEOUT_S) on its requests but caught only (aiohttp.ClientError, PermissionError). An expired total timeout surfaces as the builtin TimeoutError — an OSError, not an aiohttp.ClientError — so it escaped the handler and aborted startup. The one failure validation exists to report was the one that killed the simulator instead of degrading to "continue without HA".

OSError joins the except tuple. Four failure shapes are now pinned by tests: timeout, refused connection, unauthorized, and a bare transport error.

Verified against the installed stack (aiohttp 3.13.3, Python 3.14): issubclass(TimeoutError, aiohttp.ClientError) is False, issubclass(TimeoutError, OSError) is True, and asyncio.TimeoutError is TimeoutError.

Also

  • README carries a retirement notice: this simulator emulates firmware prior to r202633 and gives way to panelbench once that firmware ships.
  • Release 1.0.18 — version synced across pyproject.toml, __init__.py, config.yaml and the Dockerfile by the sync-version hook.

Test

451 passed, 3 failed — the 3 failures are pre-existing on main and untouched here (same counts before and after this change). They come from dependabot's ebus-sdk 0.1.5 → 0.19.0 bump in 9d4369d, which auto-merged because CI runs no test job:

  • test_graph_builder_topology.py (2) — the vendored graph_builder still calls the 0.1.x Device(parent_id=, root_id=) / add_child() API. Synthetic fixtures only; no shipped mapping uses child-of-parent, so published shapes are unaffected.
  • test_main_logging.py::test_sdk_homie_logger_still_emits_at_info — the SDK no longer pins the homie logger to INFO at import, which is the premise that guard exists to catch.

Pre-commit (the CI gate) passes clean: ruff, ruff-format, mypy --strict, sync-version.

`HAClient.async_validate` set `aiohttp.ClientTimeout(total=...)` on its
requests but caught only `(aiohttp.ClientError, PermissionError)`. An
expired total timeout surfaces as the builtin `TimeoutError`, which is an
`OSError` and not an `aiohttp.ClientError`, so it escaped and took startup
with it — the one failure the validation exists to report was the one that
killed the simulator instead of degrading to "continue without HA".

`OSError` joins the except tuple, and the four failure shapes a caller can
hit are pinned by tests: timeout, refused connection, unauthorized, and a
bare transport error.

Also records the retirement notice in the README: this simulator emulates
firmware prior to r202633 and gives way to panelbench once that ships.

Release 1.0.18.
@cayossarian
cayossarian merged commit cec3ee7 into main Aug 28, 2026
2 checks passed
@cayossarian
cayossarian deleted the fix/ha-validate-survives-timeout branch August 28, 2026 23:30
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.

1 participant