Handle GraphQL Errors
Last updated
A successful HTTP response does not always mean that every GraphQL field succeeded. Handle transport status, the top-level errors array, returned data, and typed mutation errors separately.
Check every response layer
- Treat network failures and non-success HTTP status codes as transport failures.
- Parse the JSON body only when the response declares a supported JSON content type.
- Inspect the top-level
errorsarray. - Accept partial
dataonly when your use case can safely operate without the failed fields. - For mutations, inspect the operation payload’s typed
errorsfield before using the result.
type GraphQlError = {
message: string;
path?: Array<string | number>;
extensions?: {
code?: string;
};
};
type GraphQlResponse<TData> = {
data?: TData;
errors?: GraphQlError[];
};
const requestViio = async <TData>(query: string, variables: Record<string, object | string | number | boolean | null>) => {
const response = await fetch("https://api.viio.io/graphql", {
method: "POST",
headers: {
Authorization: process.env.VIIO_API_KEY ?? "",
"Content-Type": "application/json",
},
body: JSON.stringify({ query, variables }),
});
if (!response.ok) {
throw new Error("Viio API request failed");
}
const result: GraphQlResponse<TData> = await response.json();
if (result.errors?.length) {
throw new Error("Viio API returned an unsuccessful response");
}
if (!result.data) {
throw new Error("Viio API response did not include data");
}
return result.data;
};
Protect user-facing messages
Do not display raw API error messages to end users. Log diagnostic details in an access-controlled system, then show a localized generic message such as “We couldn’t load this data. Try again.”
Never log API keys, authorization headers, complete request bodies containing sensitive variables, or personal data returned by the API.
Retry selectively
Retry transient network failures and server errors with exponential backoff and jitter. Do not automatically retry authentication failures, validation errors, or mutations unless the operation is demonstrably idempotent.