hasura/graphql-engine · error · WebSocketError
{SEC_WEBSOCKET_PROTOCOL} header: {0}
Error message
{SEC_WEBSOCKET_PROTOCOL} header: {0} What it means
The `Sec-WebSocket-Protocol` header was present but its value could not be interpreted; specifically the header value failed conversion to a string (`ToStrError` from the http crate), usually because it contains non-visible-ASCII bytes. Reported as `WebSocketError::InvalidHeaderValue` during the upgrade handshake.
Source
Thrown at v3/crates/graphql/graphql-ws/src/websocket/mod.rs:118
.insert(SEC_WEBSOCKET_ID, websocket_id.to_string().parse()?);
Ok(response)
})
},
);
result.unwrap_or_else(IntoResponse::into_response)
}
}
/// Error types for WebSocket connections.
#[derive(Debug, thiserror::Error)]
pub enum WebSocketError {
/// Error when the Sec-WebSocket-Protocol header is missing
#[error("Missing {SEC_WEBSOCKET_PROTOCOL} header")]
MissingProtocolHeader,
/// Error when the header value cannot be converted to a string
#[error("{SEC_WEBSOCKET_PROTOCOL} header: {0}")]
InvalidHeaderValue(#[from] ToStrError),
/// Error when the GraphQL WebSocket protocol is not included
#[error("Expecting {} protocol", protocol::GRAPHQL_WS_PROTOCOL)]
ExpectingGraphqlWsProtocol,
/// Error when setting the WebSocket ID header value fails in response
#[error("Unable to set {SEC_WEBSOCKET_ID} header value: {0}")]
WebSocketIdInvalidHeaderValue(#[from] InvalidHeaderValue),
}
impl tracing_util::TraceableError for WebSocketError {
fn visibility(&self) -> tracing_util::ErrorVisibility {
match self {
Self::MissingProtocolHeader
| Self::ExpectingGraphqlWsProtocol
| Self::InvalidHeaderValue(_) => tracing_util::ErrorVisibility::User,
Self::WebSocketIdInvalidHeaderValue(_) => tracing_util::ErrorVisibility::Internal,View on GitHub (pinned to 724551b9ae)
Solutions
- Capture the raw upgrade request to inspect the exact Sec-WebSocket-Protocol bytes
- Fix the client/intermediary to send a plain ASCII value such as `graphql-transport-ws`
- Remove or repair any proxy transform that rewrites the header
- If handcrafting handshakes, validate the header is visible-ASCII before sending
Example fix
# before (curl, accidental raw bytes) curl -H $'Sec-WebSocket-Protocol: graphql-transport-ws\x0b' ... # after curl -H 'Sec-WebSocket-Protocol: graphql-transport-ws' ...
Defensive patterns
Strategy: validation
Validate before calling
const proto = 'graphql-transport-ws';
if (!/^[\x21-\x7e]+$/.test(proto)) throw new Error('bad protocol header'); Try / catch
catch (e) { if (String(e).includes('Sec-WebSocket-Protocol')) { inspect raw header bytes; resend with ASCII value; } } Prevention
- Send only visible-ASCII subprotocol names
- Audit proxies that rewrite header encoding
- Dump the raw handshake when debugging
When it happens
Trigger: A client or intermediary sends a Sec-WebSocket-Protocol header value containing bytes outside visible ASCII (control characters, non-ASCII encoding), causing `to_str()` on the header value to fail when the server parses the subprotocol list.
Common situations: Malformed handcrafted WS clients; middleware or proxies that mangle header encoding (e.g. UTF-16 leaking in); corrupted header injection in test harnesses; rarely, a badly encoded library default protocol string.
Related errors
- Invalid header value: {0}
- Missing {SEC_WEBSOCKET_PROTOCOL} header
- Connection already initialized
- Invalid header name: {0}
- AuthError: {0}
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/ae42071de0ebba1c.
Report an issue: GitHub.