Skip to main content

GraphQL error handling

Riseact's GraphQL API uses two distinct mechanisms to communicate errors, depending on the context in which they occur.

Two types of error

TypeWhere it appearsWhen it is used
userErrorsIn the mutation payloadValidation and business logic errors
errors (GraphQL)At the top of the responseStructural errors, resource not found, permissions

1. userErrors - validation errors

Mutations always return a response object that includes a userErrors field. This field is null on success, or contains a list of errors if the operation did not succeed.

Structure:

type UserError {
code: ErrorCode!
field: String # specific field that caused the error, if applicable
message: String # human-readable description
}

enum ErrorCode {
BAD_INPUT # invalid or missing input
NOT_FOUND # resource not found
NOT_UNIQUE # uniqueness violation
PROTECTED # deletion blocked by dependencies
}

Example error response:

{
"data": {
"supporterCreate": {
"supporter": null,
"userErrors": [
{
"code": "BAD_INPUT",
"field": "email",
"message": "This field is required."
}
]
}
}
}

Example success response:

{
"data": {
"supporterCreate": {
"supporter": {
"id": 42,
"email": "mario@example.com"
},
"userErrors": null
}
}
}

How to handle userErrors

Always check userErrors after each mutation before using the returned data:

const { data } = await client.mutate({ mutation: CREATE_SUPPORTER, variables });

if (data.supporterCreate.userErrors?.length) {
const errors = data.supporterCreate.userErrors;
// handle errors per field
errors.forEach(err => {
console.error(`[${err.code}] ${err.field}: ${err.message}`);
});
return;
}

const supporter = data.supporterCreate.supporter;

2. GraphQL errors - structural exceptions

Some errors are not captured in the mutation payload but propagate as standard GraphQL errors, in the errors array of the response.

Common cases:

SituationError type
Resource not found in a queryGraphqlNotFound
Invalid or missing tokenauthentication error
Insufficient permissionsauthorization error
Malformed queryparsing error

Example response:

{
"data": null,
"errors": [
{
"message": "Resource not found",
"locations": [{ "line": 2, "column": 3 }],
"path": ["donation"]
}
]
}
note

The HTTP status code is almost always 200 even when GraphQL errors are present. Always check the errors field in the response, not just the HTTP status.

How to handle GraphQL errors

const response = await client.query({ query: GET_DONATION, variables: { id: 999 } });

if (response.errors?.length) {
const message = response.errors[0].message;
// e.g. "Resource not found"
console.error('GraphQL error:', message);
return;
}

async function safeMutate(client, mutation, variables) {
let response;

try {
response = await client.mutate({ mutation, variables });
} catch (networkError) {
// Network error or HTTP 5xx
throw new Error('Network error: ' + networkError.message);
}

// Structural GraphQL errors
if (response.errors?.length) {
throw new Error('GraphQL error: ' + response.errors[0].message);
}

// Business logic errors in the mutation
const rootKey = Object.keys(response.data)[0];
const result = response.data[rootKey];

if (result.userErrors?.length) {
throw new Error('Validation error: ' + result.userErrors[0].message);
}

return result;
}