1

I need to send custom error message in JSON format, from my express app, served in a lambda function using serverless-http

Please correct me if i got it wrong, but as i understand it, we need to use LAMBA_PROXY APIG integration to be able to send custom error messages defined directly from a lambda function.

This is what i have tried so far:

res.status(400).json({ message: 'email already taken' });

serverless.yml

functions:
  auth:
    handler: src/express/auth/index.handler
    name: ${self:service}-auth-${env:STAGE}
    # warmup: true
    integration: lambda-proxy
    memorySize: 128
    timeout: 15
    events:
        - http:
            path: /auth/
            method: ANY
            cors: true
        - http:
            path: /auth/{any+}
            method: ANY
            cors: true

this is what the API is returning(with status code 400)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Error</title>
    </head>
    <body>
        <pre>Bad Request</pre>
    </body>
</html>

Any leads, on how I can send a custom response, in JSON format?

update: After more tests, I found out that calling next(error) doesn't reach the last error handler


const register = async (req, res, next) {
  try {
    await verifyEmail(req.body.email);
    const user = await Users.register(req.body);
    const token = sign(user.attrs, {});
    res.json({ token, user });
  } catch (e) {
    next(e);
  }
};

const generalError = async (err, req, res, next) => {
  // doesn't reach this part! :(
  console.log('generalError handler', JSON.stringify(err));
  res.status(errorOut.status).json(errorOut);
};

ApiRouter.post('/register', register);
app.use('/auth', ApiRouter);
app.use(generalError);

1 Answer 1

2

(I just answered a very similar question here)

Yes, this is explained in the Express docs under Error Handling.

Express comes with a built-in error handler that takes care of any errors that might be encountered in the app. This default error-handling middleware function is added at the end of the middleware function stack.

If you pass an error to next() and you do not handle it in a custom error handler, it will be handled by the built-in error handler; the error will be written to the client with the stack trace. The stack trace is not included in the production environment.

To override this handler, refer to the section in the Express docs titled Writing error handlers.

It explains:

Define error-handling middleware functions in the same way as other middleware functions, except error-handling functions have four arguments instead of three: (err, req, res, next). For example:

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

You define error-handling middleware last, after other app.use() and routes calls

So in your case, if you wanted to respond with a 400 and some JSON, you might write something like this:

const serverless = require('serverless-http');
const express = require('express');
const app = express();

// Your middleware and other routes here
app.use(/* register your middleware as normal */);

// Finally, your custom error handler
app.use(function customErrorHandler(err, req, res, next) {
   res.status(400).json({ message: 'email already taken' });
});

module.exports.handler = serverless(app);
Sign up to request clarification or add additional context in comments.

4 Comments

Hey @romellem, thanks for answering! sorry for not posting into more details, but i have implemented it like this. so i have ` ApiRouter.post('/register', Controller.register); app.use(/auth, ApiRouter); /* Error Handling */ app.use(ErrorController.error404); app.use(ErrorController.generalError); ` i just found out that it doesn't reach the last error handler. i'll update question
i have updated the question. you can check the updates on the lowest part
Sounds like Lambda is overriding some default functionality of Express. You'll have to do some ore research. I found this question - stackoverflow.com/a/46697547/864233 - that might give you some more clues.
yup! there's something fishy with lambda, that the fallback middleware doesn't get called. maybe on packaging, or something else. i tried NODE_ENV=production and development with same results. now i'm tempted to call the error middleware directly from the catch block!

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.