Photo by Yosuke Ota on Unsplash

On this page

This chapter follows Object types and scalars.

Arguments attach to a single field (user(id: ID!)). Input object types group arguments for mutations and complex filters. The spec forbids using output object types as inputs, so you duplicate shape where needed—a deliberate constraint that keeps evolution predictable.

Field arguments and defaults

Arguments can be scalars, enums, lists, or input objects:

type Query {
events(
after: DateTime
limit: Int = 20
status: EventStatus = SCHEDULED
): [Event!]!
}

Default values apply when the client omits the argument. Changing a default is a behavioral change: old clients may see different results without a schema break.

Input object types

Input types use the input keyword. Fields may reference scalars, enums, or other input types—not output object types:

input CreateEventInput {
name: String!
startsAt: DateTime!
venue: VenueInput
}
input VenueInput {
city: String!
room: String
}
type Mutation {
createEvent(input: CreateEventInput!): Event!
}

The Relay mutation convention names one field input and wraps client payloads that way; many schemas follow it for consistency with codegen and libraries.

Why inputs and outputs differ

Output types can include recursive object graphs (Author.books → Book.author). Input types must be serializable trees with no cycles. You cannot pass a full Book object graph as a mutation argument unless you define a matching input shape.

That separation also lets you mark input fields optional for partial updates while keeping output fields non-null for clients reading data.

One input type per mutation

Sharing one input type across unrelated mutations couples their evolution. When CreatePostInput and UpdatePostInput diverge, shared fields like title can block you from making title optional on update only.

Prefer small, purpose-built inputs even if they look repetitive in SDL.

The @oneOf input directive

GraphQL @oneOf (when supported by your server) marks an input object where exactly one field must be provided—useful for discriminated unions in mutations:

input NotificationChannel @oneOf {
email: EmailNotification
sms: SmsNotification
}

Clients send one branch; validation fails if zero or multiple fields are set. Check your framework version; NestJS and recent spec drafts document support paths.

Where validation belongs

GraphQL validates types and requiredness before resolvers run. Business rules (unique email, stock limits) belong in resolvers or service layers and should surface as field errors or mutation payloads your schema documents.

Do not rely on GraphQL alone to enforce cross-field constraints on inputs; return structured errors your UI can display.

Next: Writing GraphQL operations.

Check your understanding

Question 1 of 6

0 of 6 checked

  1. 1. What happens when a client omits an argument that has a default in the schema?

Search articles

Type a word to search published articles.

Open the search page