Summary
The Hub UI's Console tab (Inspector REPL) fails to establish a WebSocket connection because the JavaScript client does not include the Sec-WebSocket-Protocol: rivet header when connecting to the inspector endpoint. The engine's guard requires this header and rejects the connection.
Environment
- Engine version: v2.3.9 (Docker image
rivetdev/engine:latest, SHA 40c1240705506)
- Deployment: Self-hosted via Docker Compose (single node, file system persistence)
- RivetKit: v2.3.9 (TypeScript, runner/envoy mode)
- Browser: Chrome (latest)
- OS: macOS
Steps to Reproduce
- Self-host Rivet Engine via Docker Compose with default config
- Connect an actor-runtime (runner mode) with a simple actor
- Open Hub UI at
http://localhost:6420/ui
- Navigate to an actor → click the Console tab
Expected Behavior
The Console tab opens a WebSocket connection and provides an interactive REPL to call actor actions.
Actual Behavior
The WebSocket connection fails immediately:
Engine log:
missing_header: Missing sec-websocket-protocol header.
Browser console:
WebSocket connection to 'ws://localhost:6420/gateway/{actor_id}/inspector/connect?protocol_version=6' failed: Connection closed before receiving a handshake response
WebSocket is not open. Cannot send message. [Uint8Array(2)]
Root Cause Analysis
The engine's guard requires Sec-WebSocket-Protocol: rivet on WebSocket upgrade requests to /gateway/{id}/inspector/connect. However, the Hub UI's bundled JavaScript does not include this header when creating the WebSocket:
// What the Hub UI does (missing protocol):
new WebSocket('ws://localhost:6420/gateway/{id}/inspector/connect?protocol_version=6')
// What the engine requires:
new WebSocket('ws://...', ['rivet']) // Sec-WebSocket-Protocol: rivet
Proof that the header is the only issue: Manually testing with the protocol header succeeds (101 Switching Protocols):
curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Protocol: rivet" \
'http://localhost:6420/gateway/{actor_id}/inspector/connect?protocol_version=6'
# → HTTP/1.1 101 Switching Protocols
What Still Works
All other Inspector features work correctly over HTTP:
- State/Queue/Schedules/Connections/Metadata tabs ✅
GET /gateway/{id}/inspector/rpcs → {"rpcs":["sayHi"]} ✅
POST /gateway/{id}/inspector/action/sayHi with token → returns result ✅
POST /gateway/{id}/action/sayHi (gateway action) ✅
Suggested Fix
In the Hub UI's inspector WebSocket connection code, pass the protocol as the second argument:
new WebSocket(url, ['rivet'])
This would set the Sec-WebSocket-Protocol: rivet header on the upgrade request.
Related
Summary
The Hub UI's Console tab (Inspector REPL) fails to establish a WebSocket connection because the JavaScript client does not include the
Sec-WebSocket-Protocol: rivetheader when connecting to the inspector endpoint. The engine's guard requires this header and rejects the connection.Environment
rivetdev/engine:latest, SHA40c1240705506)Steps to Reproduce
http://localhost:6420/uiExpected Behavior
The Console tab opens a WebSocket connection and provides an interactive REPL to call actor actions.
Actual Behavior
The WebSocket connection fails immediately:
Engine log:
Browser console:
Root Cause Analysis
The engine's guard requires
Sec-WebSocket-Protocol: riveton WebSocket upgrade requests to/gateway/{id}/inspector/connect. However, the Hub UI's bundled JavaScript does not include this header when creating the WebSocket:Proof that the header is the only issue: Manually testing with the protocol header succeeds (101 Switching Protocols):
What Still Works
All other Inspector features work correctly over HTTP:
GET /gateway/{id}/inspector/rpcs→{"rpcs":["sayHi"]}✅POST /gateway/{id}/inspector/action/sayHiwith token → returns result ✅POST /gateway/{id}/action/sayHi(gateway action) ✅Suggested Fix
In the Hub UI's inspector WebSocket connection code, pass the protocol as the second argument:
This would set the
Sec-WebSocket-Protocol: rivetheader on the upgrade request.Related