dgraph-io/dgraph · error

expected type for the field %s is %s but got %s in type %s

Error message

expected type for the field %s is %s but got %s in type %s

What it means

During remote GraphQL schema composition, each field of a local type is compared against the corresponding field of the remote type. When the remote field's resolved type string differs from the local field's type string, this error is thrown from matchRemoteTypes (invoked via matchDeepTypes). It guarantees the local schema stays type-compatible with the upstream remote schema before federation/joining.

Source

Thrown at graphql/schema/remote.go:393

				if remoteFields == nil {
					// Get fields for INPUT_OBJECT
					remoteFields = remoteType.InputFields
				}
				for _, field := range fields {
					var remoteField *gqlField = nil
					for _, rf := range remoteFields {
						if rf.Name == field.Name {
							remoteField = rf
						}
					}
					if remoteField == nil {
						return errors.Errorf(
							"%s field for the local type %s is not present in the remote type %s",
							field.Name, typeName, remoteType.Name,
						)
					}
					if remoteField.Type.String() != field.Type.String() {
						return errors.Errorf(
							"expected type for the field %s is %s but got %s in type %s",
							remoteField.Name,
							remoteField.Type.String(),
							field.Type.String(),
							typeName,
						)
					}
				}
			}
		}
	}
	return nil
}

// matchArgSignature matches the type signature for arguments supplied in metadata with
// corresponding remote arguments
func matchArgSignature(md *argMatchingMetadata) error {
	// TODO: maybe add path information in error messages,

View on GitHub (pinned to 759e242be6)

Solutions

  1. Diff the local type against the remote schema (graphiql introspection or `graphql-schema` diff) and update the local field definition to match remoteField.Type exactly, including NonNull and List wrappers.
  2. If the local type is authoritative, update or pin the remote schema/version so the field type matches (e.g. pin the upstream service version in config).
  3. Re-run schema composition after fixing and check the other errors it reports; usually one type change cascades into several field mismatches.
  4. If intentional divergence is needed, rename the local field/type so the matcher does not pair them.

Example fix

// before (local schema)
user: Int
// remote schema: user: String!
// after
user: String!
Defensive patterns

Strategy: validation

Validate before calling

// Before composing, diff local vs remote types
func validateFieldType(local, remote *graphql.Type) error {
    if local.String() != remote.String() {
        return fmt.Errorf("field type drift: local=%s remote=%s", local, remote.String())
    }
    return nil
}
// Run over every shared type before calling AddRemoteSchema/validateRemoteGraphql

Type guard

func typesMatch(a, b string) bool { return a == b } // compare Type.String() output including wrappers

Try / catch

if err := validateRemoteGraphql(schema, remoteSchema, query); err != nil {
    if strings.Contains(err.Error(), "expected type for the field") {
        log.Fatalf("schema drift detected: %v", err) // fix SDL, not retryable
    }
    return err
}

Prevention

When it happens

Trigger: Calling schema composition / remote merge APIs (e.g. validateRemoteGraphql / AddRemoteSchema in graphql-go/relay-style remote.go) after the upstream service changed a field's type (e.g. Int -> String, [User] -> User, String -> String!), or the local override schema declares a different type for a field that also exists remotely.

Common situations: Upstream GraphQL service upgraded and changed a field's type or nullability; a hand-written local schema in a config file drifted from the remote SDL; copying a type definition into the local schema with a slightly different wrapper ([T] vs T vs T!).

Related errors


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