0

Custom error handler:

export const errorHandler: ErrorRequestHandler = (err, _, res) => {
  if (err instanceof HttpError) {
    res.status(err.statusCode).json({
      message: err.message
    });
    return;
  }
  res.status(500).json({
    message: err.message,
  });
};

Handler where I throw the error:

export const registerHandler: Handler = async (req, res) => {
  const { username, password } = req.body as {
    username: string | undefined;
    password: string | undefined;
  };

  if (!username || !password) {
    throw new UnprocessableEntity();
  }

  try {
    const user = await User.register(username, password);
    req.logIn(user, (err) => {
      console.log(err);
    });

    res.json({
      user,
    });
  } catch (error) {
    throw new BadRequest(error.message);
  }
};

The error handler middleware works as expected when everywhere except when it is thrown in catch block of the registerHandler. It's driving me crazy. Can somebody explain why this is so?

2 Answers 2

1

middlewares are pipes, in other words functions that runs after another function, so if you want to run an error handler you need to pass the next function to run


export const registerHandler: Handler = async (req, res, next) => {
  const { username, password } = req.body as {
    username: string | undefined;
    password: string | undefined;
  };

  if (!username || !password) {
// to let express know that the next function to run is an errorhandler you need to pass a parameter to the function next
    return next(new UnprocessableEntity());
  }

  try {
    const user = await User.register(username, password);
    req.logIn(user, (err) => {
      console.log(err);
    });

    res.json({
      user,
    });
  } catch (error) {
    throw new BadRequest(error.message);
  }
};

to create error handlers you need to create a function with 4 parameter error: the error req: request res: response next: next handler

function errorHandler (error, req, res, next) {
  if (err instanceof HttpError) {
    return res.status(err.statusCode).json({
      message: err.message
    });
  }

return next(error);

}

for this to work you need to specify your error handlers after all your routes


const app = express()

app.use("/api", apiRoutes());

app.use("/more-routes", moreRoutes());

app.use(errorHandler);
app.use(anotherErrorHandler);
Sign up to request clarification or add additional context in comments.

2 Comments

I did apply the error handler middleware after all the routes and other middlewares.
"... you need to specify your error handlers after all your routes" this phrase is a life saver. Thank you.
0

This might not be the exact solution you may be looking for, but it might help.

The express js documentation says:-

  • Starting with Express 5, route handlers and middleware that return a Promise will call next(value) automatically when they reject or throw an error.

So you don't need try and catch at all.

The above code can be written as:-

  export const registerHandler: Handler = async (req, res) => {
  const { username, password } = req.body as {
    username: string | undefined;
    password: string | undefined;
  };

  if (!username || !password) {
    throw new UnprocessableEntity();
  }
   
  const user = await User.register(username, password);
  req.logIn(user, (err) => {
      console.log(err);
  });
  res.json({
      user,
  });
};

If any error occurs in await line, the errorHandler will automatically be called, and you don't have to explicitly throw an error.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.