SyntaxStudy
Sign Up
GraphQL Error Handling in Mutations
GraphQL Beginner 1 min read

Error Handling in Mutations

GraphQL always returns HTTP 200, even when errors occur. Errors are reported in a top-level errors array alongside the data field. This dual-channel approach means partial success is possible: some fields may resolve successfully while others fail. A common pattern for mutations is the "union error" approach: the mutation return type is a union of a success payload and one or more error types. This makes errors first-class citizens of the schema, allowing clients to use type-safe code to handle each error case instead of parsing free-text error messages.
Example
# ----- Union error pattern -----
type CreateUserSuccess {
  user: User!
}

type ValidationError {
  field: String!
  message: String!
}

type DuplicateEmailError {
  email: String!
  message: String!
}

union CreateUserResult =
  | CreateUserSuccess
  | ValidationError
  | DuplicateEmailError

type Mutation {
  createUser(input: CreateUserInput!): CreateUserResult!
}

# Resolver (Node.js)
# Mutation: {
#   createUser: async (_, { input }) => {
#     if (!isValidEmail(input.email)) {
#       return { __typename: 'ValidationError',
#                field: 'email', message: 'Invalid format' };
#     }
#     const exists = await User.findByEmail(input.email);
#     if (exists) {
#       return { __typename: 'DuplicateEmailError',
#                email: input.email, message: 'Already registered' };
#     }
#     const user = await User.create(input);
#     return { __typename: 'CreateUserSuccess', user };
#   }
# }

# Client query handles each case:
mutation Register($input: CreateUserInput!) {
  createUser(input: $input) {
    ... on CreateUserSuccess { user { id  email } }
    ... on ValidationError   { field  message }
    ... on DuplicateEmailError { email  message }
  }
}