How to immediately return with an error?

aws
#1

This is a followup on my confusion on how to die() with lambda {"message": "Internal server error"} on API Gateway responses with 1.5 … this time WITHOUT API Gateway.

Consider the code sample here:

$ cat handler.js
'use strict';

var AWS = require('aws-sdk');
AWS.config.region = 'ap-southeast-1';

module.exports.hello = (event, context, callback) => {
        var s3 = new AWS.S3();
        s3.listObjectsV2({ Bucket: "BLAH-BLAH-TRIGGER-AN-ERROR", Prefix: "movies/" }, (err, data) => {
                if (err) {
                        callback(err, null)
                } else {
                        console.log(data)
                }
                callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event });
        });
};
$ serverless invoke local -f hello
{
    "errorMessage": "The specified bucket does not exist",
    "errorType": "Error"
}
{
    "message": "Go Serverless v1.0! Your function executed successfully!",
    "event": ""
}

I don’t want ‘Go Serverless v1.0! Your function executed successfully!’ to run. I just want the function to end. How should I be going about it? Many thanks,

0 Likes

#2

You need to return after your callback.

callback(err, null);
return;
0 Likes

#3

oh… so what does callback actually mean? Why would you use it more than once? :thinking:

0 Likes

#4

Using callback() is optional. You only need to use it if you want to pass information back to caller. There’s a bunch of information on http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html#nodejs-prog-model-handler-callback about it.

Importantly, calling callback() doesn’t terminate your Lambda function. From what I can tell it just set the response that will be sent to the caller once your function terminates.

2 Likes

#5

A more common pattern would be the return the callback itself:

return callback(err, null);
1 Like

#6

That makes sense. Default template should have that, no? Otherwise people will get a nasty surprise like I did.

1 Like

#7

I know this is old, but I’m fairly confused here. I have the same logic going on an APIGateway, with this exact pattern (of course the result is not null, but an API response.)

It works when I invoke locally with a mock API request JSON file, but fails with an internal server error when deployed to AWS. I know it is related to this statement because if I get rid of the return, the rest of the function executes. With the return statement, it fails with no errors, just exits (due to the return.) It seems like the callback just isn’t being executed because of the return.

0 Likes

#8

@freako987 Are you using Node 8.10? Have you declared your handler async? If so you can’t use callback and need to return a value. I wrote an article explaining how async appears to work with Node 8.10 http://www.goingserverless.com/blog/how-async-lambda-handlers-work-in-node-8-10

1 Like

#9

To add to @buggy’s response, can you share some code? Is your err object empty?

0 Likes

#10

Migrated to 8.10 recently, cannot use return callback(null, response); nor callback(null, response); return.

In the doc, it implies that callback is supported, but that is not the case whenever I try to push my lambda with my serverless command.

I created a new callback function on my lambda console and set the environment to node 8.10, it worked as expected. I use similar function on serverless project, I see this Task timed out after 6.01 seconds on my cloudwatch log.

0 Likes

#11

@k1m8ee Node 8.10 supports both async and callback handler syntax. If you want more help you’ll need to post your code.

0 Likes

#12

Hi buggy, thanks for reply to my post.

I make sure that it runs on nodejs8.10

AWS lambda console;
exports.handler = (event, context, callback) => {
// TODO implement
const response = {
statusCode: 500,
body: JSON.stringify(‘Hello from Lambda!’),
};
// return response;
callback(null, response);
};

Local serverless project:

serverless yml

provider:
   name: aws
   runtime: nodejs8.10

module.exports = {
 hello: hello,
}
const response = {
     statusCode: 500,
     body: JSON.stringify('Hello from Lambda!'),
};
function hello(event, context, callback) => {
    // return response;
    callback(null, response); 
};
// Cloudwatch logs
{
  "errorMessage": "2018-12-18T12:36:56.578Z xxx Task timed out after 6.01 seconds",
  "errorType": "ReferenceError"
}

alternatively;
function hello(event, context, callback) => {
// return response;
return callback(null, response);
};

function hello(event, context, callback) => {
    // return response;
    callback(null, response); 
    return ;
};

But if i try;
async function hello(event, context, callback) => {
try {
throw ‘Ops’;
} catch (e) {
return response;
}
};

vola it works.

0 Likes

#13

Does anyone know how to write an authorizer that is defined async?

0 Likes