title: Unhandled promise rejection on AWS lambda with async / await
body: <p>Recently AWS announced the availability of the nodejs8.10 runtime for their lambda functions (<a href="https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/" rel="noreferrer">Node.js 8.10 runtime available</a>). While this seemed great for the happy flow, I'm running into some problems with the unhappy flow, i.e. I'm getting 'UnhandledPromiseRejectionWarnings'.</p>
  
  <p>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).</p>
  
  <pre><code>'use strict';
  
  const AWS = require('aws-sdk');
  
  exports.handler = async (event) =&gt; {
    let data;
    try {
      data = await getObject(event.key);
    } catch (err) {
      console.error('So this happened:', err);
      throw err;
    }
  
    return data;
  }
  
  const getObject = async (key) =&gt; {
    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');
  }
  </code></pre>
  
  <p>If I run this lambda function (with <a href="https://github.com/awslabs/aws-sam-local" rel="noreferrer">SAM local</a>) I get the error back out of the lambda like I want, but I also get the following warning(s):</p>
  
  <pre><code>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.&lt;anonymous&gt; (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
      at Request.&lt;anonymous&gt; (/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.
  </code></pre>
  
  <p>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 <a href="https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-mode-exceptions.html" rel="noreferrer">lambda function errors (node.js)</a>)</p>
  
  <p>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).</p>
  
  <pre><code>'use strict';
  
  const AWS = require('aws-sdk');
  
  exports.handler = async (event) =&gt; {
    let data;
    try {
      data = await directBoom();
    } catch (err) {
      console.error('So this happened:', err);
      throw err;
    }
  
    return data;
  }
  
  const directBoom = async () =&gt; {
    let data;
    try {
      data = await Promise.reject(new Error('boom!')); 
    } catch(err) {
      throw err;
    }
  
    return data;
  }
  </code></pre>
  
  <p>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.</p>