Skip to content

Fix timeout classification and add proxy failure-path tests - #63579

Closed
jswizzle3737 wants to merge 3 commits into
NousResearch:mainfrom
jswizzle3737:claude/test-coverage-analysis-24eciz
Closed

Fix timeout classification and add proxy failure-path tests#63579
jswizzle3737 wants to merge 3 commits into
NousResearch:mainfrom
jswizzle3737:claude/test-coverage-analysis-24eciz

Conversation

@jswizzle3737

Copy link
Copy Markdown

Summary

Fixes proxy error classification and adds deterministic failure-path tests.

aiohttp.ServerTimeoutError inherits from both asyncio.TimeoutError and aiohttp.ClientError. The existing exception order catches it as a generic client error first, returning HTTP 502 upstream_unreachable instead of HTTP 504 upstream_timeout.

This change checks asyncio.TimeoutError first and adds tests covering:

  • wrong or missing BlueBubbles webhook password → 401;
  • malformed webhook body → 400;
  • unreachable upstream → 502 upstream_unreachable; and
  • upstream timeout → 504 upstream_timeout.

The focused patch was reviewed in the fork and CodeRabbit reports success. The broader upstream suite should run in this repository's CI before merge.

claude added 3 commits July 7, 2026 06:47
- gateway/platforms/bluebubbles.py: _handle_webhook's password check
  and malformed-body handling had no failing-path coverage (fixture
  always supplied a correct secret). Add tests for wrong/missing
  password (401) and unparsable body (400).
- hermes_cli/proxy/server.py: the proxy's upstream-unreachable (502)
  and upstream-timeout (504) error mapping in _open_upstream was
  never exercised. Add tests covering both via a refused connection
  and a patched client-timeout.
Mock the connection failure instead of using a real connection to an
unused port (port 1 can be silently dropped rather than refused in
some CI/container network setups, turning a 502 test into a spurious
504), and scope both mocked exceptions to the fake upstream URL only
so the outer test client's own request to the local proxy runner is
never accidentally intercepted.
aiohttp's own sock_connect/sock_read timeout errors (ServerTimeoutError
and subclasses) inherit from both asyncio.TimeoutError and
aiohttp.ClientError. _open_upstream checked ClientError first, so every
real upstream timeout was caught there and reported as 502
upstream_unreachable instead of 504 upstream_timeout — the timeout
branch was effectively dead code. Reorder the except clauses so the
timeout check runs first, and update the 504 test to raise a real
aiohttp.ServerTimeoutError instead of a bare asyncio.TimeoutError that
doesn't occur in practice, so it actually exercises this path.

Found by chatgpt-codex-connector's review of the earlier test-coverage PR.
@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists labels Jul 13, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused fix and deterministic failure-path coverage. Current main still catches aiohttp.ClientError before asyncio.TimeoutError in hermes_cli/proxy/server.py:176-192; aiohttp's ServerTimeoutError therefore reaches the 502 branch rather than the intended 504 branch. The two upstream attempts both use _open_upstream at hermes_cli/proxy/server.py:196 and :214, so the correction applies consistently to initial and retry credentials. The proposed tests target the public proxy route while limiting interception to the fake upstream URL.

This is an automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users labels Jul 16, 2026
@jswizzle3737 jswizzle3737 closed this by deleting the head repository Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants