1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Expressのデフォルトエラーハンドリングが作動しない??

Posted at

なにが起こったか?

app.use((
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    err: any,
    req: express.Request,
    res: express.Response<BaseResponse.BaseApiResponse<{}>>,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    next: any
) => {
    SentryLib.captureException(err)
    LoggerLib.debug(`${err}`)
    res.status(500).json({
        data: {},
        error: { message: 'standard error', code: 'ServerError' },
    })
    next()
})
export default class Controller {
    /**
     *
     * @param {express.Request} req
     * @param {express.Response} res
     */
    public static async get(
        req: express.Request<
            {},
            AreaPublicApiResponse.GetApiResponse,
            any,
            {}
        >,
        res: express.Response,
        next: express.NextFunction
    ) {
        throw Error('エラーですよ')
    }
}

上記のようにデフォルトエラーハンドリングの実装を行っていて、APIで強制的にエラーを出すように設定してみたがデフォルトのエラーハンドリングが機能しない

公式を確認してみる
https://expressjs.com/ja/guide/error-handling.html

app.get('/', (req, res, next) => {
  setTimeout(() => {
    try {
      throw new Error('BROKEN')
    } catch (err) {
      next(err)
    }
  }, 100)
})

nextを実行しないとどうやらデフォルトハンドリングまで行ってくれないらしい
Railsに慣れちゃってたので、エラーが起きたら自動的に検知してくれると勘違いしていた

修正版

export default class Controller {
    /**
     *
     * @param {express.Request} req
     * @param {express.Response} res
     */
    public static async get(
        req: express.Request<
            {},
            AreaPublicApiResponse.GetApiResponse,
            any,
            {}
        >,
        res: express.Response,
        next: express.NextFunction
    ) {
        try {
        throw Error('エラーですよ')
      } catch (e) {
        next(e) // nextを実行
      }
    }
}

無事動くようになりました!

nextが呼ばれないとどうなるか

If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.
An Express application can use the following types of middleware:

ref: https://expressjs.com/en/guide/using-middleware.html

リクエストが滞留してしまうということが書かれている
同期的なエラーはExpressでデフォルトでハンドリングしてくれるが、非同期関数で発生するエラーはハンドリングしてくれないので、リクエストが滞留してしまいサーバーダウンの原因にもなってしまう恐れも

Express v 5.xでは非同期関数のエラーも自動でnext()が呼ばれるようになる

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

ref: https://expressjs.com/en/guide/error-handling.html

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?