Skip to content

Managed agents silently fail to connect when the relay is configured with localhost: harness dials 127.0.0.1 and gets a generic 404 #3033

Description

@ahmetkca

Describe the bug

If the relay is configured with localhost (which is what .env.example ships), managed agents never connect, and nothing in the desktop app says why. The agent runtime just shows stopped, and the only clue anywhere in the UI is Last error harness exited with status exit status: 1.

The cause is that the harness is handed a different host than the one configured. The desktop canonicalizes the relay URL when it builds the agent's runtime key, folding localhost to 127.0.0.1, and that canonical value is what reaches buzz-acp as BUZZ_RELAY_URL. The relay resolves a community from the literal Host header and fails closed on an unmapped host, so a relay seeded as communities.host = localhost:PORT rejects ws://127.0.0.1:PORT with a generic 404.

What made this genuinely hard to work out, and the reason I am filing this separately from the fix:

  1. The desktop app surfaces no error at all. Mentioning an agent simply does nothing.
  2. The 404 is deliberately generic, which is correct for an unmapped host so nobody can probe which hosts exist, but it means the failure carries no diagnostic signal.
  3. The desktop's own WebSocket connects fine, because it dials the URL I actually entered. So the app looks completely healthy while agents are broken. Channels work, messages work, only agents fail.
  4. The real error is written to a harness log file that nothing in the UI points you to.

Because of 3, my first assumption was that I had misconfigured the agent, or that the ACP adapter was missing, or that I had built the sidecar binaries wrong. I spent a long time on those before thinking to look for a log file. It was not obvious that the problem was the relay URL, since the relay was plainly working.

There is also no community URL that satisfies both surfaces:

Community URL entered Desktop socket Agent harness
ws://localhost:PORT connects dials 127.0.0.1:PORT, gets 404
ws://127.0.0.1:PORT gets 404 would connect

The only workaround is to move RELAY_URL away from the shipped default, or to register the community under the canonical host.

Steps to reproduce

  1. cp .env.example .env in deploy/compose and set the required values, leaving the relay host as localhost (the default RELAY_URL=ws://localhost:3000, or any port). Start the stack. The relay seeds communities.host = localhost:PORT.
  2. Build and launch the desktop app, create an identity, and add the community as ws://localhost:PORT. It connects, channels work.
  3. Add or enable a managed agent and mention it in a channel.
  4. The agent never responds. The runtime shows stopped with Last error harness exited with status exit status: 1 and no further detail in the UI.
  5. Find the harness log at ~/.local/share/xyz.block.buzz.app/agents/logs/<pubkey>__<hash>.log (path differs per platform) and you will see the actual cause:
WARN buzz_acp::relay: initial relay connect failed with terminal error:
     WebSocket error: HTTP error: 404 Not Found
Error: relay connect error: WebSocket error: HTTP error: 404 Not Found

Isolating it to the hostname, against one relay seeded as localhost:3021, changing nothing but the spelling:

$ buzz-acp --relay-url ws://localhost:3021 --agent-command claude-agent-acp
WARN buzz_acp::relay: initial relay connect failed with terminal error:
     Auth failed: restricted: not a relay member

$ buzz-acp --relay-url ws://127.0.0.1:3021 --agent-command claude-agent-acp
WARN buzz_acp::relay: initial relay connect failed with terminal error:
     WebSocket error: HTTP error: 404 Not Found

The first reaches NIP-42 auth and fails there for an unrelated and expected reason (that key was not a relay member). The second never reaches auth at all.

Expected behavior

Agents should connect to the relay the operator configured. Failing that, the failure should be visible: the harness's own error should surface in the UI rather than only exit status: 1, and the app should ideally point at the harness log.

Version and platform

  • Buzz version: built from source at main (c2a4ee71), desktop 0.4.26; relay from deploy/compose using ghcr.io/block/buzz:main
  • OS: Ubuntu 24.04.4 on WSL2

Logs / additional context

Two suggestions, both cheaper than the underlying fix and useful regardless of it:

  • Surface the harness error, not just the exit code. The harness already logs a precise, actionable message. The UI shows exit status: 1. Showing the last error line from that log, or even just linking the log path, would have saved me hours.
  • Warn when the URL handed to the harness differs from the community URL. That mismatch is exactly the bug, and it is trivially detectable at spawn time.

Possibly related: #2542 reports the identical harness exited with status exit status: 1 with "no more log", and a second person there says "Have the same issue, not really sure how to investigate". That report is a released macOS build and mentions claude code and codex being unavailable, so it may well be a different root cause (a missing ACP adapter would be my guess). I mention it because it suggests that message is a catch-all for several unrelated failures, which is the diagnosability problem above. The log path in step 5 may help the people in that thread regardless.

I have opened a PR that fixes the addressing for the spawn, reconciliation, and restore paths, and documents three restart paths it deliberately does not cover.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions