{"record":{"id":"7b0603ef6a0074b6","repo":"dgraph-io/dgraph","slug":"remote-schema-doesn-t-have-any-mutations","errorCode":null,"errorMessage":"remote schema doesn't have any mutations.","messagePattern":"remote schema doesn't have any mutations\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/schema/remote.go","lineNumber":243,"sourceCode":"// validates the graphql given in @custom->http->graphql by introspecting remote schema.\n// It assumes that the graphql syntax is correct, only remote validation is needed.\nfunc validateRemoteGraphql(metadata *remoteGraphqlMetadata) error {\n\tremoteIntrospection, err := introspectRemoteSchema(metadata.url, metadata.headers)\n\tif err != nil {\n\t\treturn err\n\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","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/schema/remote.go#L225-L261","documentation":"During validation of a @custom directive pointing at a remote GraphQL endpoint, the library introspects the remote schema. When the operation being validated is a mutation, the remote introspection result must contain a MutationType root; if the remote schema has no mutation root type, this error is returned. It means the remote endpoint simply cannot serve the mutation your custom directive references.","triggerScenarios":"A field marked with @custom graphql(...) whose operation is `mutation` is validated, and remoteIntrospection.Data.Schema.MutationType is nil in the fetched remote introspection (graphql/schema/remote.go:243).","commonSituations":"Pointing a custom mutation at an introspection URL of a read-only schema (e.g. a gateway exposing only queries, a CDN-published SDL without mutation root, or the wrong endpoint/env URL); remote service updated to remove mutations while local config still declares them.","solutions":["Verify the remote endpoint URL in the @custom directive is the correct GraphQL endpoint and that its schema actually exposes a mutation root.","Re-run the remote introspection to confirm MutationType is present; if the remote removed mutations, delete or convert the local mutation fields accordingly.","Change the operation type of the custom directive to `query` if you only intended to read data.","Check environment-specific config (staging vs prod) — some environments may disable mutations."],"exampleFix":"// before\n@custom(directive: {name: \"custom\", arguments: [{name: \"http\", value: {url: \"https://api.example.com/graphql\", method: POST}}], mode: SINGLE, operation: mutation})\n// after\n// point at an endpoint whose schema defines `type Mutation { ... }`, or switch to:\n@custom(directive: {name: \"custom\", arguments: [{name: \"http\", value: {url: \"https://api.example.com/graphql\", method: GET}}], mode: SINGLE, operation: query})","handlingStrategy":"validation","validationCode":"// before applying config, introspect the remote and check the root exists\nconst hasMutationRoot = introspection.__schema.mutationType != null\nif (opType === 'mutation' && !hasMutationRoot) {\n  throw new Error(`remote ${endpoint} has no mutation root; fix @custom directive config`)\n}","typeGuard":"function hasMutationRoot(s) { return s?.__schema?.mutationType?.name != null }","tryCatchPattern":null,"preventionTips":["Introspect the remote endpoint in CI before deploying schema config","Pin remote endpoints per environment and validate each one","Only use `mutation` operations on endpoints known to expose a MutationType"],"tags":["graphql","remote-schema","mutation","custom-directive"],"backgroundTag":"remote-schema-missing-root-type","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}