GraphQL Lists and Non-Null Types

Lists and non-null modifiers control the shape and nullability of field values. Combining them gives you precise control over what clients can and cannot receive — whether a field will always return a value, whether it might be absent, and whether it returns one item or many.

What Null Means in GraphQL

By default, every field in GraphQL is nullable. This means the server can return null for that field. The ! symbol changes this — it makes the field non-nullable, meaning the server guarantees a value will always be there.

  Field definition     What client receives
  ────────────────     ────────────────────
  name: String         "Alice"  or  null
  name: String!        "Alice"  always (never null)

The Four List Combinations

  Definition       List   List null?  Items null?  Meaning
  ──────────────   ────   ──────────  ───────────  ──────────────────────────
  [String]         Yes    Can be null Can be null  Optional list, optional items
  [String!]        Yes    Can be null Never null   Optional list, items always exist
  [String]!        Yes    Never null  Can be null  Always a list, items optional
  [String!]!       Yes    Never null  Never null   Always a list, items always exist

  Visual memory aid:
  ──────────────────
  [String!]!
   ───────         ← items inside the list: String! = never null
          ─        ← the list itself: ! = never null

Practical Examples

  type Library {
    name:    String!            ← Always a string
    motto:   String             ← May be null (not all libraries have one)
    books:   [Book!]!           ← Always a list; each book always exists
    wishlist:[Book]             ← May be null; items may be null
  }

  Possible responses for each field:
  ───────────────────────────────────
  name:     "City Library"       ✓  |  null  ✗
  motto:    "Read More"          ✓  |  null  ✓
  books:    [book1, book2]       ✓  |  []    ✓  |  null  ✗
  wishlist: [book1, null, book3] ✓  |  null  ✓

Non-Null and Error Propagation

When a non-null field resolver unexpectedly returns null, GraphQL propagates the null up to the nearest nullable parent. This error bubbling protects clients from receiving data in an inconsistent shape.

  type Order {
    id:       ID!
    customer: Customer!   ← Non-null
    items:    [Item!]!    ← Non-null
  }

  If customer resolver returns null:
  ───────────────────────────────────
  GraphQL cannot put null in customer (it's non-null!)
  → The entire order field becomes null
  → An error appears in the errors array

  Response:
  {
    "data":   { "order": null },
    "errors": [{ "message": "Cannot return null for non-nullable field Order.customer" }]
  }

Choosing the Right Combination

  Use case                         Recommended type
  ────────────────────────────────  ────────────────
  User's name (always present)      String!
  User's nickname (optional)        String
  List of products (always a list)  [Product!]!
  Optional search results           [Product!]
  Tags on a post (might be none)    [String!]!  (empty list, not null)

Key Points

  • All fields are nullable by default in GraphQL.
  • Appending ! makes a field non-nullable — the server must always return a value.
  • Square brackets [] denote a list type.
  • [Type!]! means the list itself is always returned and its items are never null — the most common choice for lists of entities.
  • A non-null field returning null at runtime triggers error propagation to the nearest nullable ancestor.

Leave a Comment