question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Errors thrown by express middleware on JSONController routes are not caught properly

See original GitHub issue

Hi there

I noticed that if I throw an error inside of a route, it is caught and the client receives a JSON body response. But if I throw an error inside of some middleware, UseBefore the route, then the error is returned as the body of the response.

For example, this is the body of the response from a custom middleware (AuthrizePlayer) that throws an error:

Error
at AuthorizePlayer.use (C:\Users\Tim\Desktop\Heroku\cargame2020\dist\Middleware\AuthorizePlayer.js:6:15)
at C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\routing-controllers\driver\express\ExpressDriver.js:381:86
at Layer.handle [as handle_request]
(C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request]
(C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\index.js:275:10)
at expressInit (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\middleware\init.js:40:5)
at Layer.handle [as handle_request]
(C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\index.js:317:13)
at C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\index.js:284:7
at Function.process_params (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\router\index.js:275:10)
at query (C:\Users\Tim\Desktop\Heroku\cargame2020\node_modules\express\lib\middleware\query.js:45:5)

Compared to the same error (new Error()) being throw inside of the route itself:

{
    "name": "Error",
    "stack": "Error\n    at PlayerController.GetMyName (C:\\Users\\Tim\\Desktop\\Heroku\\cargame2020\\dist\\Controllers\\PlayerController.js:40:19)\n    at ActionMetadata.callMethod (C:\\Users\\Tim\\Desktop\\Heroku\\cargame2020\\node_modules\\routing-controllers\\metadata\\ActionMetadata.js:108:48)\n    at C:\\Users\\Tim\\Desktop\\Heroku\\cargame2020\\node_modules\\routing-controllers\\RoutingControllers.js:99:140"
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:4
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
Kalhamacommented, Aug 28, 2020

I’m also finding this troublesome. I think middlewares and controllers should work in a similar manner.

I also noticed that returning routing-controllers custom errors (ie. throw UnauthorizedError()) yields HTTP 500 when it should return HTTP 401.

I modiefied some code that already exists in the project repo in order to have a workaround until valid stable fix is provided. Example of this workaround attached below.

import { Response } from 'express'
import { HttpError } from 'routing-controllers'

const processJsonError = (error: any): any => {
    if (typeof error.toJSON === 'function') return error.toJSON()

    let processedError: any = {}
    if (error instanceof Error) {
        const name = error?.name !== 'Error' ? error.name : error.constructor.name
        processedError.name = name

        if (error.message) processedError.message = error.message
        if (error.stack && process.env.NODE_ENV !== 'production') processedError.stack = error.stack

        Object.keys(error)
            .filter(
                (key) =>
                    key !== 'stack' &&
                    key !== 'name' &&
                    key !== 'message' &&
                    (!(error instanceof HttpError) || key !== 'httpCode')
            )
            .forEach((key) => (processedError[key] = (error as any)[key]))

        if (this.errorOverridingMap)
            Object.keys(this.errorOverridingMap)
                .filter((key) => name === key)
                .forEach((key) => (processedError = this.merge(processedError, this.errorOverridingMap[key])))

        return Object.keys(processedError).length > 0 ? processedError : undefined
    }

    return error
}

export const middlewareErrorHandler = (error, response: Response): void => {
    response.status(error.httpCode || 500)
    response.json(processJsonError(error))
}

USAGE EXAMPLE

import { ExpressMiddlewareInterface } from 'routing-controllers'
import { Request, Response } from 'express'
import { auth} from '../auth'
import { middlewareErrorHandler } from './common/middlewareErrorHandler'

export class UserMiddleware implements ExpressMiddlewareInterface {
    async use(request: Request, response: Response, next: (err?) => void): Promise<void> {
        auth()
            .then(() => next())
            .catch((err) => middlewareErrorHandler(err, response))
    }
}

0reactions
github-actions[bot]commented, Apr 3, 2022

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error handling - Express.js
Errors that occur in synchronous code inside route handlers and middleware require no extra work. If synchronous code throws an error, then Express...
Read more >
A Guide to Error Handling in Express.js | Scout APM Blog
When an error encounters synchronous code, Express catches it automatically. Here's an example of a route handler function where we simulate ...
Read more >
Error Handling in Express - Reflectoring
Handling errors thrown by asynchronous functions invoked in the routes ... The application in index.js does not contain any error handling ...
Read more >
Throwing Http Errors from middleware · Issue #248 - GitHub
Is it possible to throw http errors listed here with middleware and custom ... at routing-controllers level with try-catch and handle error:.
Read more >
Express not catching exception in middleware - Stack Overflow
I'm attempting to use middleware to catch exceptions in routes. Expected Result: When an error is thrown in a route I expect it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found