Alexandre Rey
12/15/2025, 4:38 PMDiscovered type 'process' for work pool 'openshift-pool'.
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/prefect/cli/_utilities.py", line 44, in wrapper
return fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/prefect/cli/_types.py", line 159, in sync_fn
return asyncio.run(async_fn(*args, **kwargs))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/prefect/cli/worker.py", line 168, in start
await worker.start(
File "/usr/local/lib/python3.11/site-packages/prefect/workers/process.py", line 158, in start
async with self as worker:
File "/usr/local/lib/python3.11/site-packages/prefect/workers/process.py", line 314, in __aenter__
self._runner = await self._exit_stack.enter_async_context(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/contextlib.py", line 650, in enter_async_context
result = await _enter(cm)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/prefect/runner/runner.py", line 1571, in __aenter__
self._cancelling_observer = await self._exit_stack.enter_async_context(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/contextlib.py", line 650, in enter_async_context
result = await _enter(cm)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/prefect/runner/_observers.py", line 157, in __aenter__
self._events_subscriber = await self._exit_stack.enter_async_context(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/contextlib.py", line 650, in enter_async_context
result = await _enter(cm)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/prefect/events/clients.py", line 555, in __aenter__
await self._reconnect()
File "/usr/local/lib/python3.11/site-packages/prefect/events/clients.py", line 566, in _reconnect
self._websocket = await self._connect.__aenter__()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/websockets/asyncio/client.py", line 587, in __aenter__
return await self
^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/websockets/asyncio/client.py", line 543, in __await_impl__
await self.connection.handshake(
File "/usr/local/lib/python3.11/site-packages/websockets/asyncio/client.py", line 114, in handshake
raise self.protocol.handshake_exc
File "/usr/local/lib/python3.11/site-packages/websockets/client.py", line 325, in parse
self.process_response(response)
File "/usr/local/lib/python3.11/site-packages/websockets/client.py", line 142, in process_response
raise InvalidStatus(response)
websockets.exceptions.InvalidStatus: server rejected WebSocket connection: HTTP 500
An exception occurred.
how can i fix it what are the possible issues here ?Marvin
12/15/2025, 4:38 PMMarvin
12/15/2025, 4:44 PMPREFECT_API_URL=<https://prefect.example.com/api>
- Make sure your reverse proxy/route allows WebSocket upgrades and forwards the right headers.
- Must forward Upgrade, Connection, Host, X-Forwarded-Proto, and preserve Sec-WebSocket-Protocol: prefect
- Check TLS/termination:
- If you terminate TLS at the OpenShift Route (edge/re-encrypt), make sure the worker connects via https:// and your backend service is reachable over HTTP by the router.
- If using a custom CA, ensure the worker trusts it (system trust store or set `SSL_CERT_FILE`/`REQUESTS_CA_BUNDLE`).
- If you set API auth on the server, set the matching client auth on the worker:
- Server: PREFECT_SERVER_API_AUTH_STRING
- Worker: PREFECT_API_AUTH_STRING (must match exactly)
- Get the server logs around the time of the 500 — the exception will usually be logged there and will pinpoint the root cause.
OpenShift/Ingress specifics
- OpenShift Routes support WebSockets, but you typically need longer timeouts for long‑lived connections:
apiVersion: <http://route.openshift.io/v1|route.openshift.io/v1>
kind: Route
metadata:
name: prefect-api
annotations:
<http://haproxy.router.openshift.io/timeout|haproxy.router.openshift.io/timeout>: 1h
spec:
host: <http://prefect.example.com|prefect.example.com>
to:
kind: Service
name: prefect-api
port:
targetPort: 4200
tls:
termination: edge # or reencrypt/passthrough as appropriate
insecureEdgeTerminationPolicy: Redirect
- If you use another proxy in front (NGINX/HAProxy), ensure WebSocket headers are forwarded and HTTP/1.1 is used. For example (NGINX):
location /api {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Preserve auth if you use it
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_pass <http://prefect-backend>; # your service
}
Why this fails with HTTP 500
- Missing/stripped WebSocket headers (most commonly Upgrade, Connection, or Sec-WebSocket-Protocol: prefect) cause the backend to error during handshake.
- Path rewriting that drops the /api prefix can route to the wrong handler.
- TLS/host mismatch or untrusted certs can break the connection.
- If server API auth is enabled but the worker didn’t send the matching token, the server typically returns 403 — but some proxy chains can surface this as 500.
How to validate quickly
1) Verify the API health:
curl -i <https://prefect.example.com/api/health>
2) Verify WS upgrade reaches the backend (expect 101 Switching Protocols, not 500):
curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Protocol: prefect" \
<https://prefect.example.com/api/events/out>
3) Try bypassing the Route temporarily (to isolate the router):
- From a pod in the same namespace, set PREFECT_API_URL to the internal service URL, e.g. <http://prefect-api:4200/api>, then start the worker. If it works, the Route/ingress is the culprit.
Notes about disabling events
- There isn’t a supported environment variable to disable the worker’s event/cancellation WebSocket in Prefect 3.x. If the WS cannot be established, the worker can’t finish starting. The fix is to ensure the route/proxy allows the WS handshake.Marvin
12/15/2025, 4:44 PMprefect version)
- The exact PREFECT_API_URL your worker is using
- OpenShift Route YAML (or any additional proxy config in front)
- Whether you’ve set PREFECT_SERVER_API_AUTH_STRING on the server and PREFECT_API_AUTH_STRING on the worker
- TLS termination mode (edge/reencrypt/passthrough) and whether you use a custom CA
With that, I can help you pinpoint the exact header/route change needed.