GraphQL handling GraphQL error responses

Hi, in this post we are going to learn about the process to handle GraphQL error responses and also we are going to refactor our current request.js file.

If you want to read the last post please click here GraphQL checking the browser network

If we click the company name then we are going to see another error where the company name is not defined:

Result:

And that is because we need to create another function in the request.js file where that specific function will have the GraphQL query for the company, but if you see the request.js file the structure of the current functions are similar, so let’s create a new function with the common functionality.

I created the graphqlRequest function with query and variables parameters (where variables is optional)

Then below in the same file we are going to call this graphqlResponse function inside the other functions:

// GraphQL endpoint
const endpointURL = "http://localhost:9000/graphql";

// Generic function
async function graphRequest(query, variables = {}) {
  // variables is optional
  const response = await fetch(endpointURL, {
    method: "POST",
    headers: { "content-type": "application/json" }, // The type is json
    body: JSON.stringify({
      // Convert a JavaScript object into a string
      query,
      variables,
    }),
  });

  const responseBody = await response.json(); // Converting the response to json format
  return responseBody.data;
}

//  Function that fetch data for specific Job details
export async function loadJob(id) {
  const query = `query JobQuery ($id: ID!) { 
    job(id: $id) {
      id
      title
      description
      company {
        id
        name
      }
    }
  }`;
  const { job } = await graphRequest(query, { id });

  return job;
}

// Function that will call the GraphQL endpoint passing specific query
// to get the data that the query specifies
export async function loadJobs() {
  const query = `{
    jobs {
      id 
      title
      company {
        id
        name
      }
    }
  }
`;
  const { jobs } = await graphRequest(query);

  return jobs;
}

Nice, all good, but what happen if the GraphQL server returned an error response?

For example if in the query parameter we made a syntax mistake like this:

We are asking for a field that doesn’t exist.

Result:

But at this point this message is not telling us much information about the error, so let’s open our network tab in the browser to see the http request:

If we see the Headers we have a 400 status code that is telling us that is a Bad request then open the Response tab and we are going to see a json object with an error array:

The GraphQL server could return much more usefully error message, so let’s catch GraphQL errors so in the generic function we can say:

// Generic function
async function graphRequest(query, variables = {}) {
  // variables is optional
  const response = await fetch(endpointURL, {
    method: "POST",
    headers: { "content-type": "application/json" }, // The type is json
    body: JSON.stringify({
      // Convert a JavaScript object into a string
      query,
      variables,
    }),
  });

  const responseBody = await response.json(); // Converting the response to json format

  // {"errors":[{"message":
  if (responseBody.errors) {
    throw new Error("GraphQL error");
  }

  return responseBody.data;
}

Result:

If we see the errors property is an array where the first item is an object that contain the message property:

So let’s extract that message from the response:

// Generic function
async function graphRequest(query, variables = {}) {
  // variables is optional
  const response = await fetch(endpointURL, {
    method: "POST",
    headers: { "content-type": "application/json" }, // The type is json
    body: JSON.stringify({
      // Convert a JavaScript object into a string
      query,
      variables,
    }),
  });

  const responseBody = await response.json(); // Converting the response to json format

  // {"errors":[{"message":
  if (responseBody.errors) {
    const message = responseBody.errors
      .map((error) => error.message)
      .join("\n");
    throw new Error(message);
  }

  return responseBody.data;
}

Now when I refresh I can see the error message in the browser and this is more clear for us as developers to find where the error is:

Nice, so remember if we have error we are going to see a errors array with different messages (that’s why we are using a .map())

In a production application we need to show something else that just throwing an error, for example we can display a user friendly message saying: “sorry something when wrong”

This is the entire request.js file:

// GraphQL endpoint
const endpointURL = "http://localhost:9000/graphql";

// Generic function
async function graphRequest(query, variables = {}) {
  // variables is optional
  const response = await fetch(endpointURL, {
    method: "POST",
    headers: { "content-type": "application/json" }, // The type is json
    body: JSON.stringify({
      // Convert a JavaScript object into a string
      query,
      variables,
    }),
  });

  const responseBody = await response.json(); // Converting the response to json format

  // {"errors":[{"message":
  if (responseBody.errors) {
    const message = responseBody.errors
      .map((error) => error.message)
      .join("\n");
    throw new Error(message);
  }

  return responseBody.data;
}

//  Function that fetch data for specific Job details
export async function loadJob(id) {
  const query = `query JobQuery ($id: ID!) { 
    job(id: $id) {
      id
      title
      description
      company {
        id
        name
      }
    }
  }`;
  const { job } = await graphRequest(query, { id });

  return job;
}

// Function that will call the GraphQL endpoint passing specific query
// to get the data that the query specifies
export async function loadJobs() {
  const query = `{
    jobs {
      id 
      title
      company {
        id
        name
      }
    }
  }
`;
  const { jobs } = await graphRequest(query);

  return jobs;
}

By Cristina Rojas.