<@ULVA73B9P> i get this error `websockets.exceptio...
# marvin-ai
b
@Marvin i get this error
websockets.exceptions.InvalidStatus: server rejected WebSocket connection: HTTP 403
when self hosting my prefect server using docker compose :
prefect.server.utilities.subscriptions - WebSocket connection rejected: 'prefect' subprotocol required when auth is configured
m
thought for 186.6 seconds
Thanks for the error details — that message means the server is enforcing API auth and rejected the WebSocket handshake because the client’s handshake did not include the required “prefect” subprotocol. What’s happening - In Prefect 3.x, when API auth is enabled on the server (
PREFECT_SERVER_API_AUTH_STRING
), all WebSocket connections must: - Include the
Sec-WebSocket-Protocol: prefect
subprotocol on the initial handshake - Perform a small auth handshake once connected - The official Prefect UI and Python clients do send this subprotocol automatically. When this error appears, it’s almost always because a reverse proxy (e.g., nginx/Traefik) between the client and your server is not forwarding the
Sec-WebSocket-Protocol
header. How to fix 1) If you’re using a reverse proxy, ensure it preserves the WebSocket headers, especially
Sec-WebSocket-Protocol
. - nginx example (critical lines annotated):
Copy code
location / {
  proxy_pass <http://prefect_server>;          # your upstream
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Host $host;

  # CRITICAL: make sure these WS headers are forwarded
  proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol;
  proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
  proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
  proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;

  # Optional to avoid timeouts on long-lived WS
  proxy_read_timeout 7d;
  proxy_send_timeout 7d;
}
- Traefik generally preserves WS headers by default. Make sure you are not using a headers middleware that overwrites or drops
Sec-WebSocket-Protocol
, and that you are not terminating/rewriting the WS route in a way that strips it. 2) Make sure both sides have matching auth strings - Server: set in your server container
Copy code
PREFECT_SERVER_API_AUTH_STRING="user:password"
- Clients (agents, workers, any Python clients): set
Copy code
PREFECT_API_AUTH_STRING="user:password"
These must match exactly. 3) Quick isolation tests - Bypass the proxy temporarily: point
PREFECT_API_URL
at the server container’s host:port directly and try again. If it works direct but fails via proxy, it’s the header forwarding. - Use a WS client to verify the subprotocol reaches the server:
Copy code
wscat -c <wss://your-domain.example.com/api/>... -H "Sec-WebSocket-Protocol: prefect"
If the server accepts with auth enabled, the subprotocol made it through. References (source) - Server check that enforces the subprotocol when auth is enabled: subscriptions.py - Python clients sending the “prefect” subprotocol: events/clients.py - Server-side API auth setting: settings/models/server/api.py If you can share: - Your docker-compose for the server - Any nginx/Traefik (or other proxy) config in front of Prefect - Whether you set
PREFECT_SERVER_API_AUTH_STRING
and where your clients run …I can spot-check and suggest exact edits for your setup.