$cd ../troubleshooting/
Lowπ Connectivity#WebSocket
Gateway WebSocket Keeps Disconnecting and Reconnecting
// The browser control UI shows a never-ending 'Connecting...' spinner, or the gateway shows repeated WebSocket upgrade failures. Usually caused by a stale auth token or missing CORS origin header.
rotate_token.sh
β Fix 1 β Clear Auth Token and Re-login
Stale tokens cause WebSocket 401 β rapid reconnect loop
# Clear stale auth token from browser
localStorage.removeItem('openclaw_token')
# Or use the CLI to regenerate token
openclaw auth rotate
# Then reload the Control UIcors.yaml
β Fix 2 β Add Your Origin to CORS Allowlist
Add your actual origin β wildcard '*' is disabled by default
# In openclaw.yaml
gateway:
cors:
origins:
- http://localhost:3000
- https://your-custom-domain.com
- http://192.168.1.100:3000 # Local IP if accessing from LANnginx.conf
β Fix 3 β Check Gateway Port and Reverse Proxy Headers
nginx WebSocket proxy config
# nginx example β add to your location block
location /ws {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400; # 24h to prevent timeout disconnects
}βΉ Common Behind a Reverse Proxy
If OpenClaw is behind nginx/Caddy/Traefik, ensure the WebSocket upgrade headers (Upgrade, Connection, Sec-WebSocket-*) are being properly forwarded. Missing headers cause the 101 Switching Protocols handshake to fail.
β Heartbeat Leakingβ All Issues
β FAQ
Q1. How do I know if my auth token is stale?
Check the gateway logs for '401 Unauthorized' or 'token expired' messages. You can also open your browser's DevTools β Network tab and filter by 'WS' to see WebSocket requests β a rapidly cycling connection with status 401 is the clearest sign. Regenerate tokens with 'openclaw gateway auth-token --show' on the server side, then clear localStorage in your browser ('localStorage.clear()') to force a new login.
Q2. Does this happen behind a reverse proxy?
Yes, this is actually the most common cause. Reverse proxies (nginx, Caddy, Traefik, HAProxy) that don't forward WebSocket upgrade headers will cause the handshake to fail and the browser to retry immediately, creating a loop. The fix is adding the WebSocket headers to your proxy config: Upgrade, Connection, Host, and a long proxy_read_timeout (86400 for 24 hours). Without the timeout extension, the proxy will close the connection after 60-90 seconds.
Q3. Can I disable the Control UI entirely?
Yes. Set 'gateway: ui: false' in config.yaml and restart the gateway. The agent still works fully via CLI and messaging channels (Telegram, WhatsApp, Discord) without the web UI. This also reduces attack surface if you're running OpenClaw on a public server without proper HTTPS.
Q4. The WebSocket connects briefly but then disconnects every 60-90 seconds. What's wrong?
This is almost always a reverse proxy timeout. The proxy is closing idle WebSocket connections after its default read timeout (typically 60s for nginx). Add 'proxy_read_timeout 86400;' to your nginx location block to extend it to 24 hours. For Caddy, add 'transport http { read_buffer 4096 }' or use the '@websocket' matcher. For Traefik, the WebSocket timeout is controlled by the 'readTimeout' in the router configuration.
Q5. I see a CORS error in the browser console. How do I fix it?
CORS errors happen when the Origin header of your browser request doesn't match the allowed origins in openclaw.yaml. Add your exact origin (scheme + domain + port) to the cors.origins list. Common mistakes: forgetting the port number ('http://localhost' vs 'http://localhost:3000'), using http vs https, or using a wildcard ('*') which OpenClaw disables by default for security. Check the exact Origin value in your browser's DevTools β Network β request headers.
Q6. The reconnect loop only happens for some users but not others. Why?
This suggests the issue is specific to certain browsers, network conditions, or sessions rather than a server-side configuration problem. Common causes: (1) One user has a stale cached auth token while others have fresh ones. (2) A corporate VPN or firewall on that user's network is killing WebSocket connections. (3) The user is on a different subnet that isn't in the CORS allowlist. Ask the affected user to try from a different browser or network to narrow it down.