0

Suppose I have the following async function

export async function someAsyncFunction() {
  const result = await fetchData();
  return result[0].id;
}

In the route I have

router.post(
  '/some-path',
  handleErrorAsync(async (req: Request, resp: Response, _err: Errback) => {
    const data = await someAsyncFunction();
    resp.json(data)
  })
);

And I have error handling functionalities that do

interface ResponseError extends Error {
  statusCode: number;
}

// Middleware to respond with an error when error caught
export function handleError(
  err: ResponseError,
  _req: Request,
  resp: Response,
  _next: NextFunction
) {
  if (err) {
    resp.status(err.statusCode || 500).json(err);
  }
}

export const handleErrorAsync = (func: Function) => (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  func(req, res, next).catch((error: Error) => {
    next(error);
  });
};

So this works fine if for example fetchData has an error response object, but this fails to print error objects when the error is a regular javascript error and instead it just prints {} with 500 error.

For example in this line return result[0].id; if the result is empty ([]), then this would throw TypeError, which will be caught by the handleError middleware, but then the .json(err) part will show only {}

Is there a way I can get both the servers errors (which are working correctly) and the internal server errors with that same middleware?

0

4 Answers 4

1

res.json do JSON.parse which returns an empty object {}.

I can suggest destructuring the err body.

 resp.status(err.statusCode || 500).json({message:err.message, error:err});

This will give you a message for every Native Error

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! This helped! Another solution was to use npmjs.com/package/serialize-error
1

You could extend the toJSON method of Error.

let a = new Error("hi")

console.log(JSON.stringify(a))

Error.prototype.toJSON = function () {
    const alt = {};
    // get all property
    Object.getOwnPropertyNames(this).forEach((key) => {
        alt[key] = this[key];
    });

    // only get message property
    // alt["message"] = this["message"]
    return alt;
}

console.log(JSON.stringify(a))

Then just call res.json(error), and you'll get the property of Error.
Because when you call res.json(parameter), express will trigger the toJSON method of parameter. You could read more in Is it not possible to stringify an Error using JSON.stringify? .
But, I recommend only expose the "message" property in toJSON method.

1 Comment

Thanks for this answer, and for the link which led me to use npmjs.com/package/serialize-error and it fixed the problem!
0

I would suggest using res.send() in the error handler like

return res.status(500).send(err.message);

Comments

0

I fixed the issue using https://www.npmjs.com/package/serialize-error

import { serializeError } from 'serialize-error';

  if (err) {
    resp
      .status(err.statusCode || 500)
      .json(serializeError(err));
  }

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.