100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
GraphQL

Nullable vs Non-Nullable Types

Why fields are nullable by default in GraphQL, what the `!` modifier guarantees, and how null bubbling propagates a single resolver failure up the response tree.

Schema DesignIntermediate8 min readJul 10, 2026
Analogies

Nullable vs Non-Nullable Types

In GraphQL, every field is nullable by default — a String field can resolve to null unless it's explicitly marked with a trailing exclamation mark as String!, meaning the server promises it will never return null for that field. This inverts the assumption many REST APIs implicitly make; GraphQL forces the schema author to be deliberate about which fields are guaranteed and which are optional, and that guarantee becomes part of the public contract clients can rely on without defensive null-checking.

🏏

Cricket analogy: A player's 'currentTeam' field might be null for a retired player, but 'name' should never be null for a valid player record — just as GraphQL lets a schema author mark certain fields as always-present (name: String!) while others stay optional.

Error Propagation and Null Bubbling

The real power of non-null types shows up during error handling: if a resolver for a non-null field (Type!) throws an error or returns null unexpectedly, GraphQL doesn't just null out that single field — it propagates the null upward to the nearest nullable ancestor field, potentially nulling out an entire object or list to preserve the schema's guarantee. This 'null bubbling' means a single failed non-null leaf field can wipe out much more of the response than expected, so schema authors have to weigh the convenience of a strict guarantee against the blast radius of a single resolver failure.

🏏

Cricket analogy: If a mandatory 'runsScored' stat fails to load for one ball in an over, and the field is marked non-null, the whole over's data can be wiped from the response rather than just that one ball — like GraphQL's null bubbling escalating a single failure upward.

graphql
type Team {
  id: ID!
  name: String!
  currentSponsor: String   # nullable — a team may have no sponsor
}

type Match {
  id: ID!
  homeTeam: Team!          # non-null — a match always has a home team
  result: String           # nullable — result is null before the match ends
}

query {
  match(id: "m-102") {
    homeTeam {
      name
    }
    result
  }
}

A common pattern is to make list items non-null but the list itself nullable ([Player!]) — an empty or absent list is still valid, but if the list exists, none of its entries should ever be null, which is a stronger and more common guarantee than [Player]! or [Player!]!.

Overusing ! on fields backed by unreliable data sources (flaky third-party APIs, optional joins) is a common mistake — a single transient failure on a deeply-nested non-null field can null out a much larger portion of the response than the actual failure warrants, degrading the client experience more than a nullable field with a documented 'may be null on error' contract would.

  • Fields are nullable by default in GraphQL; ! marks a field as guaranteed non-null.
  • Non-null is a promise the schema author makes to clients, allowing them to skip defensive null checks.
  • If a non-null field's resolver errors or returns null, GraphQL bubbles the null up to the nearest nullable ancestor.
  • Null bubbling can null out an entire object or list because of a single deeply-nested non-null failure.
  • [Type!] (nullable list of non-null items) is a common, safer pattern than a fully non-null list.
  • Overusing ! on fields backed by unreliable data sources increases the blast radius of a single failure.

Practice what you learned

Was this page helpful?

Topics covered

#GraphQL#GraphQLStudyNotes#WebDevelopment#NullableVsNonNullableTypes#Nullable#Non#Types#Error#APIs#StudyNotes#SkillVeris