`mqtt_manager.publish_command` builds an unsubscribed dash-format `reply_to` topic — every start/stop/config command produces a dead-letter reply and an EMQX AUTHZ denial

Open Beginner friendly
#256 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
1/5
Estimated time
Under an hour
Newbie friendliness
88/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
api, backend

Research direction

Read utils/mqtt_manager.py: compare the subscription on line 63, the generic RPC reply_to on lines 363-365, and the publish_command() header on line 460. The callers are in services/bots_orchestrator.py (start, stop, import_strategy, config). Align or drop the reply_to value in publish_command(), then confirm a start/stop command no longer produces an EMQX AUTHZ denial on hummingbot-api-response-<ts>.

Written by the indexing model from the issue text.

Description

bug
Describe the bug

Summary

MQTTManager.publish_command() embeds a reply_to header in a format that nothing in the stack consumes:

  • the API itself never subscribes to it (its subscription is slash-format),
  • with the official hummingbot/deploy emqx/acl.conf (deny-by-default), the broker rejects the bot's reply publish with not_authorized.

Commands still execute (responses travel on hbot/<bot>/response/..., which is subscribed and ACL-allowed), so the impact today is log noise plus a wasted publish per command — but the reply_to value is inconsistent with the module's own RPC path and with its own subscription list, and it will bite anyone who starts relying on it.

Environment

  • hummingbot-api: Docker Hub hummingbot/hummingbot-api:latest / 1.0.1 (both refreshed 2026-11-13); same code present on current main
  • bot: hummingbot/hummingbot:latest (20260922) — version-independent, the bot only echoes the reply_to it received (hummingbot/remote_iface/mqtt.py publishes the response back to reply_to verbatim)
  • broker: EMQX 5 with the official hummingbot-deploy deny-by-default emqx/acl.conf

Root cause

Three topic forms coexist in the same module:

# utils/mqtt_manager.py (v1.0.1 line numbers; same code on main)

# L63 — what the API subscribes to:
("hummingbot-api/response/+", 1),  # RPC responses to our reply_to topics

# L363-365 — generic RPC path (consistent, works):
reply_to_topic = f"hummingbot-api/response/{timestamp}"

# L460 — publish_command() header (inconsistent, dead letter):
"reply_to": f"hummingbot-api-response-{int(time.time() * 1000)}",  # Unique response topic

publish_command() is fire-and-forget (returns after publish(); no future is registered against this reply_to), so the dash topic has no consumer even on the API side — the message is a dead letter regardless of ACL.

Observed behavior

With the official deploy ACL (allows only hbot/# and hummingbot-api/response/#):

[warning] tag: AUTHZ, clientid: hbot.<bot-name>, username: admin,
topic: hummingbot-api-response-1794732006067, reason: not_authorized,
msg: cannot_publish_to_topic_due_to_not_authorized

one line per start / stop / import_strategy / config command (all four go through publish_command, see services/bots_orchestrator.py). Note the topic is a single level (hummingbot-api-response-<ts>), so the deploy ACL cannot allow it without weakening to a bare +.

Impact

  • Functional: none today. Commands are delivered and executed; actual command responses arrive on hbot/<bot>/response/... (_handle_command_response), and state telemetry flows on hbot/#. Verified end-to-end (deploy → start → hot config update → stop-and-archive) with a live strategy.
  • Noise: linear with command volume — one AUTHZ warning per command on the broker, one failed publish per command on the bot.
  • Misleading during troubleshooting — the warnings look like a broken control channel but are unrelated to any functional symptom.
  • Latent risk: any future code that starts honoring reply_to on this path will silently never receive responses.

Suggested fix

In publish_command(), either drop the reply_to header field (nothing consumes it on this path) or align it with the subscribed form:

"reply_to": f"hummingbot-api/response/{int(time.time() * 1000)}",
Steps to reproduce bug
  1. Run the hummingbot-deploy compose stack (EMQX + api) with the stock emqx/acl.conf.
  2. Deploy a bot, then POST /bot-orchestration/stop-bot (or start / config — any publish_command caller).
  3. Check the EMQX dashboard/log for the AUTHZ denial on hummingbot-api-response-<ts>, and note the command still executes via the hbot/<bot>/response channel.
Dominant language
Python
Stars
154
Forks
208
Avg merge
2d 2h
Merged PRs (30d)
2

Getting set up

  • Ships a Dockerfile or Docker Compose file
  • No pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from hummingbot/hummingbot-api

All issues in hummingbot/hummingbot-api

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.