Home > OS >  Is it correct to throw an Error inside the catch block?
Is it correct to throw an Error inside the catch block?

Time:02-05

I'm writing a middleware that has a services layer and a controller layer. In order to transmit a clear error message to the user, I catch any errors in the services layer and then throw a new Error with a personalized message, like this:

// services.js
  async getOneRecord(id) {
    const url = this.url   `/${id}`;
    return await axios.get(url).then((res) => res.data);
  }

// UserServices.js
    async getTaxValue(id) {
    try {
      const user = await this.getOneRecord(id);
      return Number(user.tax) / 100;
    } catch (error) {
      throw new Error(`User ID not found: ${id}`);
    }
  }

// UserController.js
  static async getUserTax(req, res) {
    const { userId } = req.params;

    try {
      const user = await userServices.getTaxValue(userId);
      return res.status(200).json(user);
    } catch (error) {
      return res.status(404).json(error.message);
    }
  }

I would like to find out if this is the right way to treat errors or if I'm doing something wrong.

CodePudding user response:

Yes, it's correct and normal to throw new errors in catch blocks.

However, it is not a good practice to ignore the error that you caught. There are a lot of things that can go wrong in getTaxValue, and I would argue that most of them should not result in an "id not found" error. So be very explicit about the error that you expect, test for it with a condition, and rethrow everything else unchanged. Also set the .cause of errors.

In your case, that might be (handling only 404 errors from the user record endpoint):

class NotFoundError extends Error {}

async getTaxValue(id) {
  try {
    const user = await this.getOneRecord(id);
    return Number(user.tax) / 100;
  } catch (error) {
    if (error.response && error.response.status == 404) { // see AxiosError
      throw new NotFoundError(`User ID not found: ${id}`, {cause: error});
    }
    throw error;
  }
}

// UserController.js
async function getUserTax(req, res) {
  const { userId } = req.params;
  try {
    const user = await userServices.getTaxValue(userId);
    return res.status(200).json(user);
  } catch (error) {
    return res.status(error instanceof NotFoundError ? 404 : 500).json(error.message);
  }
}
  • Related