Shiladitya Thakur
Shiladitya Thakur

Reputation: 330

why is my express error handler not working?

I have an error handler middleware that is supposed to catch any thrown errors and display them in a serialized format.

Error handler middleware

import { NextFunction, Request, Response } from "express";
import { CustomError } from "../errors/custom-error";

export const errorHandler = (err:Error, req:Request, res:Response, next:NextFunction) => {
    if(err instanceof CustomError){
        return res.status(err.statusCode).send({errors: err.serializeErrors() })
    }
    res.status(400).send({message: [{message:'Something went wrong'}] })
}

Not-Found-error.ts

export class NotFoundError extends CustomError{
    statusCode = 404
    constructor(){
        super('Not found error')
        Object.setPrototypeOf(this, NotFoundError.prototype)
    }

    serializeErrors(){
        return [{ message: 'Not found'}]
    }
}

Custom-Error.ts

export abstract class CustomError extends Error{
    abstract statusCode: number

    constructor(message: string){
        super(message)
        Object.setPrototypeOf(this, CustomError.prototype)
    }

    abstract serializeErrors() : {
        message: string,
        field?: string
    }[]
}

index.ts

import express from 'express'
import { errorHandler } from './middleware/error-handler';
import router from './router'    

const app = express()
app.use(express.json())
app.use('/api/users', router)
app.use(errorHandler)
const PORT = 8000
app.listen(PORT, () => {
    console.log("working on port ",PORT)
})

router.ts

import express from 'express'
import { NotFoundError } from './errors/not-found';
const router = express.Router()
router.all('/*', async (req, res) => {
    throw new NotFoundError()
})
export default router

Expected behaviour:

  1. An incorrect URL is supplied
  2. A NotFoundError is thrown
  3. NotFoundError being a subclass of CustomError would have 2 attributes: statusCode and serializeErrors function
  4. The middleware catches the error and sends back appropriate response

Actual behaviour:

UnhandledPromiseRejectionWarning: Error: Not found error

UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by re jecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see http s://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

Any help or suggestion is greatly appreciated.

Upvotes: 0

Views: 841

Answers (1)

distrill
distrill

Reputation: 76

You don't want to throw the error in your handler directly, because express is async code and it will just get swallowed. You need to pass that error through the next function, so that express knows what to do with it.

import express from 'express'
import { NotFoundError } from './errors/not-found';
const router = express.Router()
router.all('/*', async (req, res, next) => {
    return next(new NotFoundError());
})
export default router

Upvotes: 1

Related Questions