{"record":{"id":"5a9f56c5f11380ca","repo":"dgraph-io/dgraph","slug":"given-graphql-operation-is-not-a-subscription","errorCode":null,"errorMessage":"given GraphQL operation is not a subscription","messagePattern":"given GraphQL operation is not a subscription","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/resolve/resolver.go","lineNumber":622,"sourceCode":"\t\t\tres, allSuccessful = r.resolvers.mutationResolverFor(m).Resolve(ctx, m)\n\t\t\taddResult(resp, res)\n\t\t}\n\tcase op.IsSubscription():\n\t\tresolveQueries()\n\t}\n\n\treturn resp\n}\n\n// ValidateSubscription will check the given subscription query is valid or not.\nfunc (r *RequestResolver) ValidateSubscription(req *schema.Request) error {\n\top, err := r.schema.Operation(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !op.IsSubscription() {\n\t\treturn errors.New(\"given GraphQL operation is not a subscription\")\n\t}\n\n\tfor _, q := range op.Queries() {\n\t\tfor _, field := range q.SelectionSet() {\n\t\t\tif err := validateCustomFieldsRecursively(field); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (r *RequestResolver) Schema() schema.Schema {\n\treturn r.schema\n}\n\n// validateCustomFieldsRecursively will return err if the given field is custom or any of its\n// children is type of a custom field.","sourceCodeStart":604,"sourceCodeEnd":640,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/resolve/resolver.go#L604-L640","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (sent to /graphql/subscriptions)\nquery { getUsers { name } }\n// after\nsubscription { getUser(...) { name } }","handlingStrategy":"validation","validationCode":"function assertSubscription(doc) {\n  const op = getOperationAST(doc, opName)\n  if (!op || op.operation !== 'subscription') {\n    throw new Error('operation must be a subscription')\n  }\n}","typeGuard":"func isSubscriptionOp(op schema.Operation) bool { return op != nil && op.IsSubscription() }","tryCatchPattern":"err := resolver.ValidateSubscription(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"not a subscription\") {\n  // route the request to the normal /graphql endpoint instead\n  resp = resolver.Resolve(ctx, req)\n}","preventionTips":["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"],"tags":["graphql","subscription","validation","dgraph"],"backgroundTag":"not-a-subscription","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}