GraphQL in Production · GraphQL Fundamentals for API Designers

Error Handling: errors[] vs Errors as Data

Separate system failures from expected business outcomes.

Create a free account to save this page, take notes and track your progress. Sign in

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.

Was this page helpful?