GraphQL in Production · GraphQL Fundamentals for API Designers

Error Handling: errors[] vs Errors as Data

Separate system failures from expected business outcomes.

The GraphQL response has data and errors; errors include message, path, locations and extensions (use extensions.code for machine-readable codes). Use the errors array for unexpected failures (resolver crashed, service down, auth failure). Model expected business outcomes as data: userErrors in payloads or result unions (union CheckoutResult = Order | PaymentDeclined | OutOfStock), which clients must handle explicitly and type-check. GraphQL-over-HTTP defines status codes: 200 for executed operations (even with field errors) using application/graphql-response+json, 4xx for requests that fail validation/parsing.

Ways to model errors

Criterion errors[] array userErrors in payload Result unions
Best for Unexpected/system errors Validation messages Distinct business outcomes
Type-safe on client No (stringly) Partly (codes) Yes (__typename)
Partial data Yes N/A N/A
Schema overhead None Low Medium
union CheckoutResult = CheckoutSuccess | PaymentDeclined | OutOfStock

type CheckoutSuccess { order: Order! }
type PaymentDeclined { reason: String!  retryable: Boolean! }
type OutOfStock { sku: String!  available: Int! }

type Mutation { checkout(input: CheckoutInput!): CheckoutResult! }

# Client
mutation { checkout(input: {...}) {
  __typename
  ... on CheckoutSuccess { order { id } }
  ... on PaymentDeclined { reason retryable }
  ... on OutOfStock { sku available }
} }

Common pitfalls

  • Business outcomes thrown as exceptions clients can't type-check.
  • Leaking stack traces in error messages.
  • Clients ignoring errors when data is partially present.

Key points

  • System errors → errors[] with extensions.code
  • Business outcomes → data (userErrors/unions)
  • Follow GraphQL-over-HTTP status rules

Further reading: GraphQL spec: Errors

Practice questions

Why model 'payment declined' as data instead of an error?

Answer

It's an expected outcome that clients must handle; as a union member it's typed, discoverable in the schema and forces explicit handling, while errors[] is untyped.

Can a GraphQL response contain both data and errors?

Answer

Yes. Partial success is normal: successfully resolved fields are returned in data, failed ones are null with corresponding entries in errors.

Open in the app to mark lessons complete, take notes and track your progress.