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

  1. Set the client's subprotocol to match --server-protocol (e.g. new WebSocket(url, '<protocol>') or the equivalent option in your client library).
  2. Compare the exact --server-protocol value on the server command line with the client's Sec-WebSocket-Protocol header (check for typos/case).
  3. If no subprotocol should be required, remove the --server-protocol option so the check is skipped.
  4. 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

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)