hasura/graphql-engine · error · FieldError
subscription are not supported over HTTP
Error message
subscription are not supported over HTTP
What it means
FieldError::SubscriptionsNotSupported — a GraphQL subscription operation was sent over the plain HTTP transport, which this engine only handles for queries and mutations. The error is deterministic: the HTTP execution path explicitly rejects subscription operations.
Source
Thrown at v3/crates/execute/src/error.rs:41
/// Field errors are raised during execution from a root field
/// Ref: <https://spec.graphql.org/October2021/#sec-Errors.Field-errors>
#[allow(clippy::duplicated_attributes)] // suppress spurious warnings from Clippy
#[derive(Error, Debug, Transitive)]
#[transitive(from(json::Error, FieldInternalError))]
#[transitive(from(NDCUnexpectedError, FieldInternalError))]
#[transitive(from(gql::normalized_ast::Error, FieldInternalError))]
#[transitive(from(gql::introspection::Error, FieldInternalError))]
#[transitive(from(FilterPredicateError, FieldInternalError))]
pub enum FieldError {
#[error("error from data source: {}", connector_error.error_response.message())]
NDCExpected {
connector_error: ndc_client::ConnectorError,
},
#[error("field '{field_name:} not found in _Service")]
FieldNotFoundInService { field_name: String },
#[error("subscription are not supported over HTTP")]
SubscriptionsNotSupported,
#[error(
"Relationship '{name}' is either remote or not having 'relation_comparisons' NDC capability; not supported for filtering"
)]
RelationshipPredicatesNotSupported { name: RelationshipName },
#[error("internal error: {0}")]
InternalError(#[from] FieldInternalError),
}
impl FieldError {
fn get_details(&self) -> Option<serde_json::Value> {
match self {
Self::NDCExpected { connector_error } => {
Some(connector_error.error_response.details().clone())
}
Self::InternalError(internal) => internal.get_details(),View on GitHub (pinned to 724551b9ae)
Solutions
- Use the WebSocket (graphql-ws/subscription-transport-ws) endpoint for subscriptions
- Change the operation to a query/mutation if realtime behavior isn't needed
- Configure your GraphQL client (urql/apollo-relay etc.) to route subscriptions to the WS URL
Example fix
# before
POST /graphql { "query": "subscription { userAdded { id } }" }
# after
# connect via websocket
new GraphQLWsLink(new WebSocketClient('wss://host/graphql')) Defensive patterns
Strategy: validation
Validate before calling
import { parse } from 'graphql';
const opType = parse(query).definitions[0].operation;
if (opType === 'subscription') throw new Error('use the WebSocket endpoint for subscriptions'); Type guard
fn is_subscription(doc: &graphql::Request) -> bool { /* inspect parsed operation type */ true } Try / catch
Match FieldError::SubscriptionsNotSupported and return an HTTP 400 with a message directing the client to the WebSocket endpoint.
Prevention
- Configure GraphQL clients with a WS link for subscriptions
- Reject subscription documents at the gateway HTTP layer early
- Document transport requirements for each operation type
When it happens
Trigger: Sending a subscription document (operation type 'subscription') to the engine's HTTP endpoint, e.g. POST /graphql with a subscription query, instead of opening a WebSocket connection.
Common situations: Clients or tools defaulting to HTTP for all operation types, missing WebSocket configuration in the GraphQL client, or test scripts POSTing subscription queries.
Related errors
- Connection already initialized
- Invalid header name: {0}
- Expecting {} protocol
- Connection initialization timed out
- Unable to parse WebSocket message: {0}
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/5e977042b21d25a3.
Report an issue: GitHub.