hasura/graphql-engine · error · ParseError
Unable to fetch message from WebSocket: {0}
Error message
Unable to fetch message from WebSocket: {0} What it means
This variant of ParseError wraps an axum::Error raised while reading the next message from the underlying WebSocket stream in the graphql-ws message pump task. It indicates a transport-level failure (socket closed, protocol violation, IO error) rather than a GraphQL-level problem. The message pump surfaces it so the connection can be torn down and traced.
Source
Thrown at v3/crates/graphql/graphql-ws/src/websocket/tasks.rs:164
})
},
)
.await
.into_inner();
if break_loop == BreakLoop::Break {
break;
}
}
}
enum ParsedClientMessage {
Close,
Protocol(protocol::types::ClientMessage),
}
#[derive(thiserror::Error, Debug)]
enum ParseError {
#[error("Unable to fetch message from WebSocket: {0}")]
WebSocket(#[from] axum::Error),
#[error("Unable to parse WebSocket message: {0}")]
Json(#[from] serde_json::Error),
}
impl tracing_util::TraceableError for ParseError {
fn visibility(&self) -> tracing_util::ErrorVisibility {
tracing_util::ErrorVisibility::User
}
}
fn parse_incoming_message(
message: Result<ws::Message, axum::Error>,
) -> Result<ParsedClientMessage, ParseError> {
let tracer = tracing_util::global_tracer();
tracer.in_span(
"parse_incoming_message",
"Parse WebSocket message frame",View on GitHub (pinned to 724551b9ae)
Solutions
- Check server logs for the underlying axum error cause to identify whether it's a clean close vs an IO failure
- Verify network stability and proxy/load-balancer idle timeout settings for WebSocket connections
- Ensure the client uses a standards-compliant WebSocket implementation and handles reconnects (graphql-ws retry semantics)
Defensive patterns
Strategy: retry
Try / catch
// On the client: treat socket errors as transient and reconnect with backoff client.dispose(); setTimeout(() => reconnect(), backoffMs());
Prevention
- Enable keep-alive/ping frames so intermediaries don't drop idle sockets
- Raise load-balancer idle timeouts for WebSocket routes
- Use a client with built-in reconnect (graphql-ws retry) for transient transport failures
When it happens
Trigger: The peer abruptly closes or resets the TCP connection, the socket enters an invalid WebSocket frame state, or an IO error occurs while the server awaits the next message via the axum WebSocket stream API.
Common situations: Clients dropping connections (mobile networks, page reloads, load balancer idle timeouts killing sockets), malformed WebSocket frames from non-conformant clients, proxies interrupting the stream.
Related errors
- subscription are not supported over HTTP
- Connection already initialized
- Invalid header name: {0}
- Expecting {} protocol
- Connection initialization timed out
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/baf4d9226af48f2d.
Report an issue: GitHub.