{"record":{"id":"3b1ad08469233dd6","repo":"dgraph-io/dgraph","slug":"found-s-operation-it-can-only-have-query-mutat","errorCode":null,"errorMessage":"found `%s` operation, it can only have query/mutation.","messagePattern":"found `(.+?)` operation, it can only have query/mutation\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/schema/remote.go","lineNumber":249,"sourceCode":"\t}\n\n\tvar remoteQueryTypename string\n\toperationType := string(metadata.graphqlOpDef.Operation)\n\tswitch operationType {\n\tcase \"query\":\n\t\tif remoteIntrospection.Data.Schema.QueryType == nil {\n\t\t\treturn errors.Errorf(\"remote schema doesn't have any queries.\")\n\t\t}\n\t\tremoteQueryTypename = remoteIntrospection.Data.Schema.QueryType.Name\n\tcase \"mutation\":\n\t\tif remoteIntrospection.Data.Schema.MutationType == nil {\n\t\t\treturn errors.Errorf(\"remote schema doesn't have any mutations.\")\n\t\t}\n\t\tremoteQueryTypename = remoteIntrospection.Data.Schema.MutationType.Name\n\tdefault:\n\t\t// this case is not possible as we are validating the operation to be query/mutation in\n\t\t// @custom directive validation\n\t\treturn errors.Errorf(\"found `%s` operation, it can only have query/mutation.\", operationType)\n\t}\n\n\tremoteTypes := make(map[string]*types)\n\tfor _, typ := range remoteIntrospection.Data.Schema.Types {\n\t\tremoteTypes[typ.Name] = typ\n\t}\n\n\tremoteQryType, ok := remoteTypes[remoteQueryTypename]\n\tif !ok {\n\t\treturn missingRemoteTypeError(remoteQueryTypename)\n\t}\n\n\t// check whether given query/mutation is present in remote schema\n\tvar introspectedRemoteQuery *gqlField\n\tgivenQuery := metadata.graphqlOpDef.SelectionSet[0].(*ast.Field)\n\tfor _, remoteQuery := range remoteQryType.Fields {\n\t\tif remoteQuery.Name == givenQuery.Name {\n\t\t\tintrospectedRemoteQuery = remoteQuery","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/schema/remote.go#L231-L267","documentation":"validateRemoteGraphql only accepts `query` or `mutation` as the operation type of a custom directive. If any other value reaches the switch's default branch, this error is returned with the offending operation name. The comment notes upstream @custom directive validation normally prevents this, so hitting it signals a validation gap or unexpected configuration.","triggerScenarios":"A @custom directive whose `operation` argument resolves to something other than \"query\" or \"mutation\" (e.g. `subscription`, misspelled value, or programmatic construction of the directive config bypassing normal validation) reaches validateRemoteGraphql.","commonSituations":"Typos like `operation: queries`, using a subscription over a remote HTTP custom directive, or tooling that generates the config schema incorrectly; older/newer config versions where operation validation rules changed.","solutions":["Set the custom directive's operation argument to exactly `query` or `mutation`.","Ensure the upstream @custom directive validation runs (the operation is normally rejected earlier); fix config generation that skips it.","If you need subscriptions, use a supported subscription mechanism instead of a remote HTTP custom directive."],"exampleFix":"// before\n@custom(directive: {name: \"custom\", arguments: [{name: \"http\", value: {url: \"https://api.example.com/graphql\"}}], mode: SINGLE, operation: subscription})\n// after\n@custom(directive: {name: \"custom\", arguments: [{name: \"http\", value: {url: \"https://api.example.com/graphql\"}}], mode: SINGLE, operation: query})","handlingStrategy":"validation","validationCode":"const ALLOWED = ['query', 'mutation']\nif (!ALLOWED.includes(config.operation)) {\n  throw new Error(`@custom operation must be query or mutation, got: ${config.operation}`)\n}","typeGuard":"function isValidOperation(op) { return op === 'query' || op === 'mutation' }","tryCatchPattern":null,"preventionTips":["Validate custom directive configs against a JSON schema before applying","Never hand-write operation strings; use config generation tooling","Reject subscriptions for HTTP-based custom directives at config time"],"tags":["graphql","custom-directive","operation-type","config-validation"],"backgroundTag":"invalid-operation-for-type","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}