Recently AWS announced the availability of the nodejs8.10 runtime for their lambda functions (Node.js 8.10 runtime available). While this seemed great for the happy flow, I'm running into some problems with the unhappy flow, i.e. I'm getting 'UnhandledPromiseRejectionWarnings'.
I'm using the below code. The idea is that I provide a key to a non-existent object to test out the unhappy flow for that scenario. My goal is for the error to get logged and propagated out of the lambda since I have no sane way of handling it here (I have no way to retrieve a new key within this lambda function). I also would like to be able to use the error in the caller (e.g. another lambda function or step functions).
'use strict';
const AWS = require('aws-sdk');
exports.handler = async (event) => {
let data;
try {
data = await getObject(event.key);
} catch (err) {
console.error('So this happened:', err);
throw err;
}
return data;
}
const getObject = async (key) => {
let params = {
Bucket: process.env.BUCKET,
Key: key
};
const s3 = new AWS.S3();
let data;
try {
data = await s3.getObject(params).promise();
} catch(err) {
console.log('Error retrieving object');
throw err;
}
console.log('Retrieved data');
return data.Body.toString('utf8');
}
If I run this lambda function (with SAM local) I get the error back out of the lambda like I want, but I also get the following warning(s):
2018-04-18T07:54:16.217Z 6ecc84eb-46f6-1b08-23fb-46de7c5ba6eb (node:1) UnhandledPromiseRejectionWarning: NoSuchKey: The specified key does not exist.
at Request.extractError (/var/task/node_modules/aws-sdk/lib/services/s3.js:577:35)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/task/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
2018-04-18T07:54:16.218Z 6ecc84eb-46f6-1b08-23fb-46de7c5ba6eb (node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
2018-04-18T07:54:16.218Z 6ecc84eb-46f6-1b08-23fb-46de7c5ba6eb (node:1) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I'm not sure how to handle this while still propagating the error out of the lambda function (which should be a valid scenario according to lambda function errors (node.js))
I've also tried running a similar (to me) scenario like the one below (to try and pinpoint and understand the error) but somehow here I do not get the warning and it is working as intended (the error is returned from the lambda function).
'use strict';
const AWS = require('aws-sdk');
exports.handler = async (event) => {
let data;
try {
data = await directBoom();
} catch (err) {
console.error('So this happened:', err);
throw err;
}
return data;
}
const directBoom = async () => {
let data;
try {
data = await Promise.reject(new Error('boom!'));
} catch(err) {
throw err;
}
return data;
}
What am I missing here and why are the two examples behaving differently? How do I get rid of the warning in the first example while still being able to propagate the error out of the lambda function? Any help would be appreciated.