RabbitMQ Error: 'WebSocket connection failed' with the Web-STOMP Plugin
Fix RabbitMQ Web-STOMP 'WebSocket connection to ws://.../ws failed' errors: diagnose the disabled plugin, wrong port, reverse-proxy Upgrade headers, TLS, and STOMP login failures.
- #rabbitmq
- #messaging
- #troubleshooting
- #errors
Stuck on this RabbitMQ error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Exact Error Message
WebSocket connection to 'ws://rabbit.example.com/ws' failed:
Error during WebSocket handshake: Unexpected response code: 200
Whoops! Lost connection to ws://rabbit.example.com/ws
In the RabbitMQ log you may instead see the STOMP side reject the socket:
2026-07-17 09:41:22.108 [warning] <0.1487.0> STOMP error frame sent:
Message: "Bad CONNECT", Detail: "Access refused for user 'guest'\n"
2026-07-17 09:41:22.109 [info] <0.1487.0> closing STOMP connection <0.1487.0> (127.0.0.1:54120 -> 127.0.0.1:15674)
What It Means
Web-STOMP exposes RabbitMQ’s STOMP protocol over a WebSocket so browser clients can talk to the broker directly. The connection travels through several layers: the browser opens a WebSocket, RabbitMQ’s rabbitmq_web_stomp plugin accepts the HTTP Upgrade, and the STOMP protocol handler then authenticates the CONNECT frame.
A handshake failure means the browser never reached a live WebSocket listener. Unexpected response code: 200 (or 404/301) almost always means a reverse proxy answered instead of forwarding the Upgrade, or the request hit the wrong port. If the WebSocket opens but the session drops immediately, the problem has moved up the stack to STOMP authentication or a virtual-host permission.
Common Causes
- The
rabbitmq_web_stompplugin (and its dependencyrabbitmq_stomp) is not enabled. - The client points at the wrong port: Web-STOMP listens on 15674 (WS) / 15673 (WSS), not the STOMP TCP port 61613.
- A reverse proxy (Nginx, HAProxy, Traefik) is not forwarding the
Upgrade/Connectionheaders, so the handshake never becomes a WebSocket. - TLS mismatch: the page is served over HTTPS but connects with
ws://, which browsers block as mixed content. - The
guestuser is being used from a non-loopback origin, where RabbitMQ refuses it by default. - A firewall or security group blocks 15674/15673 between the browser (or proxy) and the broker.
Diagnostic Commands
Confirm the plugin is actually running:
rabbitmq-plugins list -e | grep -E 'web_stomp|stomp'
Check that the Web-STOMP listener is bound and on which port:
rabbitmq-diagnostics listeners
Interface: [::], port: 15674, protocol: http/web-stomp, purpose: WebSocket and HTTP API
Interface: [::], port: 61613, protocol: stomp, purpose: STOMP
Test the raw handshake straight to the broker, bypassing any proxy:
curl -i -N \
-H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
http://rabbit.example.com:15674/ws
A working listener returns HTTP/1.1 101 Switching Protocols. Anything else (200, 404, 301) points at the proxy or a wrong path.
Step-by-Step Resolution
- Enable the plugin if it is missing. This also enables the
rabbitmq_stompdependency:
rabbitmq-plugins enable rabbitmq_web_stomp
- Point the client at the correct URL and path. The default endpoint is
/ws:
const client = new StompJs.Client({
brokerURL: "wss://rabbit.example.com/ws",
connectHeaders: { login: "app", passcode: "s3cret", host: "/prod" },
});
- Fix the reverse proxy so it forwards the WebSocket upgrade. For Nginx:
location /ws {
proxy_pass http://127.0.0.1:15674;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
}
- If you serve the app over HTTPS, terminate TLS at the proxy and use
wss://, or enable a WSS listener directly on the broker:
# /etc/rabbitmq/rabbitmq.conf
web_stomp.ssl.port = 15673
web_stomp.ssl.cacertfile = /etc/rabbitmq/certs/ca.pem
web_stomp.ssl.certfile = /etc/rabbitmq/certs/server.pem
web_stomp.ssl.keyfile = /etc/rabbitmq/certs/server-key.pem
- Stop using
guestfrom the browser. Create a dedicated user with permissions on the target vhost:
rabbitmqctl add_user app 's3cret'
rabbitmqctl set_permissions -p /prod app ".*" ".*" ".*"
- Restart the node (or the plugin) and re-test the handshake:
rabbitmq-diagnostics listeners
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
http://rabbit.example.com:15674/ws
HTTP/1.1 101 Switching Protocols
Prevention
- Bake
rabbitmq_web_stompintoenabled_pluginsso it survives node rebuilds instead of being enabled by hand. - Standardize on
wss://end-to-end in production and reservews://for local development only. - Keep proxy timeouts (
proxy_read_timeout, HAProxytimeout tunnel) long enough that idle WebSockets are not culled mid-session. - Never expose
guest; provision per-application users scoped to a single vhost. - Add a synthetic check that opens a WebSocket and sends a STOMP
CONNECTso a broken proxy config is caught before users are. - When designing browser messaging flows, use battle-tested prompts from the DevOps prompt library to review your STOMP client and proxy setup.
Related Errors
Bad CONNECT / Access refused for user 'guest'— STOMP authentication failure rather than a handshake failure.Error during WebSocket handshake: Unexpected response code: 404— wrong path or the plugin disabled.rabbitmq_stomp plugin is not enabled— the STOMP dependency is missing under Web-STOMP.NOT_ALLOWED - access to vhost '/prod' refused— the user exists but lacks vhost permissions.
Frequently Asked Questions
Which port does Web-STOMP use? Plain WebSocket traffic uses 15674 and TLS (WSS) uses 15673 by default; these are separate from the raw STOMP TCP port 61613.
Why do I get response code 200 instead of a WebSocket? A reverse proxy is answering the request itself instead of forwarding the Upgrade and Connection: upgrade headers, so the handshake never completes.
Can I connect with the guest user from a browser? No. RabbitMQ restricts guest to loopback connections by default, so browser clients must use a dedicated user with explicit vhost permissions.
Do I need both stomp and web_stomp plugins? Enabling rabbitmq_web_stomp automatically pulls in rabbitmq_stomp, but both must show as enabled in rabbitmq-plugins list -e. For more messaging fixes, see the RabbitMQ guides.
Fixed it? Get 500 RabbitMQ & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.