Skip to content

fix(gateway/bluebubbles): skip webhook server bind in standalone send path - #12439

Closed
Wonham wants to merge 1 commit into
NousResearch:mainfrom
Wonham:fix/bluebubbles-standalone-send-port-bind
Closed

fix(gateway/bluebubbles): skip webhook server bind in standalone send path#12439
Wonham wants to merge 1 commit into
NousResearch:mainfrom
Wonham:fix/bluebubbles-standalone-send-port-bind

Conversation

@Wonham

@Wonham Wonham commented Apr 19, 2026

Copy link
Copy Markdown

What broke

Standalone outbound senders — send_message_tool and cron delivery via CLI (hermes cron run) — call BlueBubblesAdapter.connect() before sending. connect() unconditionally starts an aiohttp TCPSite to listen for inbound webhooks. When the gateway is already running, that port is already held, and the bind raises:

[Errno 48] error while attempting to bind on address ('127.0.0.1', 28789): address already in use

The send fails even though the BlueBubbles server is reachable and the outbound REST API works fine.

Root cause

connect() always executes the full lifecycle: verify server → start webhook listener → register webhook URL. The webhook listener is only needed to receive inbound events. Outbound-only callers have no use for it and must not bind a port that may already be held by the running gateway.

Fix

Add a keyword-only send_only: bool = False flag to connect(). When True, the method returns after verifying server reachability and marking the adapter connected — skipping TCPSite.start() and _register_webhook().

disconnect() and _unregister_webhook() already guard against _runner=None and no registered webhook, so no changes are needed there.

Pass send_only=True from _send_bluebubbles() in send_message_tool.py — the only standalone send path for BlueBubbles.

What I tested

  • 45 existing BlueBubbles unit tests pass unchanged (tests/gateway/test_bluebubbles.py)
  • Confirmed reproduce path: cron delivery via CLI against a running gateway previously failed with the bind error above; with this fix it succeeds

… path

Standalone outbound senders (cron delivery via CLI, send_message_tool)
call BlueBubblesAdapter.connect() to verify server reachability before
sending.  connect() unconditionally binds a local TCP port for the
inbound webhook server.  When the gateway is already running, that port
is already held — the bind raises [Errno 48] and the send fails.

Root cause: connect() always starts an aiohttp TCPSite on webhook_port.
The port is only needed to *receive* inbound events; outbound-only
callers have no use for it.

Fix: add a keyword-only send_only=True flag to connect(). When set,
connect returns after verifying server reachability without starting
the webhook listener or registering a webhook URL. disconnect() and
_unregister_webhook() already guard against _runner=None / no
registered webhook, so no further changes are needed there.

Pass send_only=True from _send_bluebubbles() in send_message_tool.py,
the only standalone send path for BlueBubbles.

45 existing BlueBubbles unit tests pass unchanged.
@Bartok9

Bartok9 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Salvaged onto current main as #51763 with credit to you, @Wonham. The standalone send path still calls the full connect() (which binds the webhook port and fails with EADDRINUSE when the gateway holds it), so the bug is live. I carried your connect(send_only=True) design and added a regression test (TestBlueBubblesConnectSendOnly) that fails without the kwarg. Happy to defer if you would rather refresh this branch yourself. 🙏

Wonham commented Jun 24, 2026

Copy link
Copy Markdown
Author

Thanks for salvaging this onto current main as #51763 and for keeping the attribution. I agree that #51763 can supersede this PR. I'll leave this open for now while #51763 is still in flight, and close this one once the replacement lands.

@Bartok9

Bartok9 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Sounds good — thanks, @Wonham. I'll keep #51763 moving and ping here once it lands so you can close this out. Appreciate the collaboration. 🙏

Wonham commented Jun 24, 2026

Copy link
Copy Markdown
Author

@Bartok9 One small attribution request before #51763 lands: could you please add a Co-authored-by: Wonham <37282558+Wonham@users.noreply.github.com> trailer to the final commit there, so GitHub records the contribution correctly?

Thanks again for carrying this forward.

@Bartok9

Bartok9 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Done — added Co-authored-by: Wonham <37282558+Wonham@users.noreply.github.com> to the final commit on #51763 (now 5e8f955c8). GitHub will record your contribution on merge. I'll ping here once it lands so you can close this out. Thanks again! 🙏

@Wonham Wonham closed this by deleting the head repository Jul 5, 2026
Bartok9 pushed a commit to Bartok9/hermes-agent that referenced this pull request Aug 1, 2026
…alvage of NousResearch#12439 by @Wonham)

Rebuilt on latest main (Bartok9 hygiene 2026-08-01).
Original: NousResearch#51763
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants