dgraph-io/dgraph · error
given GraphQL operation is not a subscription
Error message
given GraphQL operation is not a subscription
What it means
ValidateSubscription checks that a GraphQL request sent over the subscription websocket/endpoint actually is a subscription operation. If schema.Operation(req) resolves to a query or mutation instead, this error is returned. Dgraph subscriptions only support subscription operations, so sending a plain query or mutation to the subscription API fails validation.
Source
Thrown at graphql/resolve/resolver.go:622
res, allSuccessful = r.resolvers.mutationResolverFor(m).Resolve(ctx, m)
addResult(resp, res)
}
case op.IsSubscription():
resolveQueries()
}
return resp
}
// ValidateSubscription will check the given subscription query is valid or not.
func (r *RequestResolver) ValidateSubscription(req *schema.Request) error {
op, err := r.schema.Operation(req)
if err != nil {
return err
}
if !op.IsSubscription() {
return errors.New("given GraphQL operation is not a subscription")
}
for _, q := range op.Queries() {
for _, field := range q.SelectionSet() {
if err := validateCustomFieldsRecursively(field); err != nil {
return err
}
}
}
return nil
}
func (r *RequestResolver) Schema() schema.Schema {
return r.schema
}
// validateCustomFieldsRecursively will return err if the given field is custom or any of its
// children is type of a custom field.View on GitHub (pinned to 759e242be6)
Solutions
- Send only subscription operations (subscription { ... }) to the subscription endpoint
- Point ordinary queries/mutations at the normal /graphql endpoint
- If using named operations, ensure the operation selected for the subscription connection is a subscription
Example fix
// before (sent to /graphql/subscriptions)
query { getUsers { name } }
// after
subscription { getUser(...) { name } } Defensive patterns
Strategy: validation
Validate before calling
function assertSubscription(doc) {
const op = getOperationAST(doc, opName)
if (!op || op.operation !== 'subscription') {
throw new Error('operation must be a subscription')
}
} Type guard
func isSubscriptionOp(op schema.Operation) bool { return op != nil && op.IsSubscription() } Try / catch
err := resolver.ValidateSubscription(ctx, req)
if err != nil && strings.Contains(err.Error(), "not a subscription") {
// route the request to the normal /graphql endpoint instead
resp = resolver.Resolve(ctx, req)
} Prevention
- Point query/mutation traffic at /graphql and subscriptions at /graphql/subscriptions
- Configure the client to route by operation type
- Validate operation type before opening a websocket
When it happens
Trigger: POSTing a query/mutation document to the /graphql/subscriptions endpoint; a client sends a named operation that is a query while expecting subscription behavior; multiplexed operation documents where the selected operation is not a subscription.
Common situations: Clients configured with the wrong endpoint URL; GraphQL clients like Apollo that auto-route based on operation type but hit Dgraph's subscription URL for all operations; testing subscription support with an ordinary query document.
Related errors
- POST method cannot have query parameters in url: %s
- remote schema doesn't have any queries.
- NQuad failed sanity check. Subject: %q, Predicate: %q, Objec
- empty variable name in function call
- empty facetKeys not allowed
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/5a9f56c5f11380ca.
Report an issue: GitHub.