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

  1. Send only subscription operations (subscription { ... }) to the subscription endpoint
  2. Point ordinary queries/mutations at the normal /graphql endpoint
  3. 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

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


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/5a9f56c5f11380ca. Report an issue: GitHub.