Course outline

GraphQL / Basic: language and response contracts / Lesson 3

Queries, arguments and variables

Build reusable named operations and distinguish omitted input from explicit null.

About 4 min readContent reviewed
On this page

Lesson goals

  • Declare variables that satisfy argument positions and keep values out of query text.
  • Predict argument defaults, required inputs and alias response keys.

Keep operation structure stable

A query selects fields and passes named arguments. The operation name identifies a particular use case, while variables carry changing values. This separation makes documents reviewable, cacheable at the document level and easier to identify in traces. It also avoids constructing language syntax by concatenating user text. Variables do not automatically sanitize downstream SQL or enforce authorization; they give GraphQL a typed input boundary. The resolver must still call its data source with that source’s safe parameterization and the caller’s permitted scope.

Pair a typed document with a JSON map

Assume course(id: ID!) returns the synthetic visible course c1. The variable declaration requires a non-null ID and the JSON map supplies its value. The operation can be reused for another allowed identifier without changing the document text. A missing required variable fails input coercion before field execution. Preserve types when serializing JSON: a boolean must be true rather than the string "true" for a Boolean variable. Exact error wording varies by implementation, so classify the stage and field instead of matching one library message globally.

graphql Reusable operation document
query CourseCard($id: ID!) {
  course(id: $id) { id title }
}

Send variables {"id":"c1"}. The document and variables are separate members of an HTTP request body when HTTP is used.

Omission is not an explicit null value

Optional arguments and variables may have defaults. Omitting a value allows the relevant default rules to apply; explicitly providing null communicates a value and does not mean use the default. This distinction becomes especially important for update inputs, where omission can mean preserve and null can mean clear. A variable’s declared type must also be valid at its argument position, with specification rules accounting for applicable defaults. Prefer simple compatible declarations in introductory operations rather than relying on subtle nullable-variable exceptions without tests.

Use aliases when argument sets differ

Aliases change response keys, not the schema field’s identity or permission rules. Selecting course twice with different IDs under the same response name creates a field-merging conflict. Distinct aliases communicate two separate result positions. The server may resolve them concurrently and no ordering guarantee should be inferred from their placement in the query. The fixture below assumes both objects are visible and have the stated titles. If one lookup is unavailable, its nullable result can be null without necessarily removing the other object.

graphql Two lookups with distinct response names
query CompareCards {
  first: course(id: "c1") { title }
  second: course(id: "c2") { title }
}
Expected output
{"data":{"first":{"title":"Graph foundations"},"second":{"title":"Graph practice"}}}

For titles Graph foundations and Graph practice, first and second appear as distinct JSON keys. Aliases are not a cache or access boundary.

Review documents with their variable fixtures

A document that validates with one fixture can still fail with a missing variable, a wrong JSON type or an input outside an application limit. Keep tests for required, omitted, null and boundary values next to the operation. If a document contains multiple operations, the request must choose the intended operation by name. Do not place sensitive variable values in URLs merely to make a request easier to inspect; logs and browser history can retain them. Transport choices and document correctness require separate reviews.

Common errors and fixes

A String variable is used where ID! is required

Why it happens
Similar serialized values were mistaken for compatible declared types.
How to fix it
Declare the variable with the required compatible GraphQL type.
Prevent it next time
Validate documents in addition to inspecting JSON samples.

Explicit null unexpectedly clears a field

Why it happens
The client used null to mean omit.
How to fix it
Remove the member when preserve is the documented operation.
Prevent it next time
Test omitted, null and concrete input separately.

Two differently parameterized fields conflict

Why it happens
Both selections have the same response key.
How to fix it
Assign clear aliases for the distinct selections.
Prevent it next time
Review field merging while composing documents.

Check your understanding

1. An optional limit defaults to 20. Is sending null identical to omitting limit?

Show worked solution

No. Omission lets a defined default apply; explicit null is a supplied null and must satisfy the argument’s contract and resolver policy. Write fixtures for omitted, null, zero and a positive limit. If the API forbids null, represent that through an appropriate schema and clear validation rather than silently substituting values in unrelated clients.

2. Why does variable use not make string-built SQL safe automatically?

Show worked solution

GraphQL validates the variable against its input type, but the resolver controls how it reaches the source. Concatenating that string into SQL can still be unsafe. Use the database driver’s parameter binding and apply business authorization. Keep the operation document stable for review, but test the downstream adapter independently because each boundary has different semantics.

Key takeaways

  • Stable documents and typed variables simplify review without replacing source safety.
  • Omitted values, nulls and defaults are distinct contract cases.

Official references