vi/websocat · error
Requested Sec-WebSocket-Protocol does not match…
Error message
Requested Sec-WebSocket-Protocol does not match --server-protocol option
What it means
Raised during WebSocket upgrade in ws_upgrade_peer when the client's Sec-WebSocket-Protocol header does not include any protocol listed via the --server-protocol option. The server rejects the handshake, logs a warning, and returns a simple_err wrapped as a WebSocketError::IoError, aborting the upgrade. This is a deliberate protocol-negotiation check to enforce that clients speak one of the allowed subprotocols.
Solutions
- Set the client's subprotocol to match --server-protocol (e.g. new WebSocket(url, '<protocol>') or the equivalent option in your client library).
- Compare the exact --server-protocol value on the server command line with the client's Sec-WebSocket-Protocol header (check for typos/case).
- If no subprotocol should be required, remove the --server-protocol option so the check is skipped.
- Confirm the server was restarted after changing --server-protocol and that no proxy strips the Sec-WebSocket-Protocol header.
Example fix
// before: client does not request the subprotocol
const ws = new WebSocket("ws://host:8080/echo");
// after: request the protocol the server requires (--server-protocol chat)
const ws = new WebSocket("ws://host:8080/echo", "chat"); Defensive patterns
Strategy: validation
Validate before calling
// Client-side pre-check before connecting (JS)
const required = "chat"; // must equal server's --server-protocol
if (!required) throw new Error("--server-protocol value must be known to the client");
const ws = new WebSocket(url, required); Try / catch
ws.addEventListener("error", () => {
// rejected handshake: subprotocol did not match --server-protocol
console.error("Upgrade rejected: Sec-WebSocket-Protocol mismatch; check --server-protocol");
}); Prevention
- Always pass the subprotocol in the client constructor when the server sets --server-protocol.
- Keep the protocol string in shared config on both sides instead of hardcoding.
- Test handshake with a raw client (curl/websocat) showing the Sec-WebSocket-Protocol header after any server config change.
When it happens
Trigger: A WebSocket client connects to the server (ws_upgrade_peer, invoked from construct) with a Sec-WebSocket-Protocol header that does not match the value(s) given to --server-protocol, or omits the header entirely while --server-protocol is configured and protocol_check fails.
Common situations: Client was not configured with the required subprotocol (e.g. browser WebSocket without the protocols argument); mismatch between --server-protocol on the server and the client library's subprotocol option; typos or case variations in the protocol name; server config updated but clients not redeployed.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
AI-assisted analysis of vi/websocat@3a3574cd2f (2026-09-12).
Data as JSON: /api/errors/7587737eeecf4015.
Report an issue: GitHub.
Appendix: source
Thrown at src/ws_server_peer.rs:189
);
}
}
}
}
for (hn, hv) in custom_reply_headers {
x.headers.append_raw(hn, hv);
}
debug!("{:?}", x.request);
debug!("{:?}", x.headers);
if !protocol_check {
return Box::new(
x.reject()
.and_then(|_| {
warn!("Requested Sec-WebSocket-Protocol does not match --server-protocol option");
::futures::future::err(crate::util::simple_err(
"Requested Sec-WebSocket-Protocol does not match --server-protocol option"
.to_string(),
))
})
.map_err(|e| websocket::WebSocketError::IoError(io_other_error(e))),
)
as Box<dyn Future<Item = Peer, Error = websocket::WebSocketError>>;
}
match l2r {
L2rUser::FillIn(ref y) => {
let uri = &x.request.subject.1;
let mut z = y.borrow_mut();
z.uri = Some(format!("{}", uri));
let h : &websocket::header::Headers = &x.request.headers;
for q in opts.headers_to_env.iter() {View on GitHub (pinned to 3a3574cd2f)