Async/await not working as expected in lambda function

This works locally on netlify dev, I still get the first Buffer() depreciation warning, but when I push it to production it completely breaks.

I first get this error:

ERROR	(node:7) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
1:34:02 PM: Duration: 1831.45 ms	Memory Usage: 18 MB

and then:

unhandled Promise Rejection 	{"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"FetchError: request to https://db.fauna.com/ failed, reason: Client network socket disconnected before secure TLS connection was established","reason":{"errorType":"FetchError","errorMessage":"request to https://db.fauna.com/ failed, reason: Client network socket disconnected before secure TLS connection was established","code":"ECONNRESET","message":"request to https://db.fauna.com/ failed, reason: Client network socket disconnected before secure TLS connection was established","type":"system","errno":"ECONNRESET","stack":["FetchError: request to https://db.fauna.com/ failed, reason: Client network socket disconnected before secure TLS connection was established","    at ClientRequest.<anonymous> (/var/task/src/built-lambda/reservation-create.js:6:31572)","    at ClientRequest.emit (events.js:310:20)","    at TLSSocket.socketErrorListener (_http_client.js:426:9)","    at TLSSocket.emit (events.js:310:20)","    at emitErrorNT (internal/streams/destroy.js:92:8)","    at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)","    at processTicksAndRejections (internal/process/task_queues.js:84:21)"]},"promise":{},"stack": 
        ["Runtime.UnhandledPromiseRejection: FetchError: request to https://db.fauna.com/ failed, reason: Client network socket disconnected before secure TLS connection was established"," at process.<anonymous> (/var/runtime/index.js:35:15)","  at process.emit (events.js:310:20)"," at processPromiseRejections (internal/process/promises.js:209:33)"," at processTicksAndRejections (internal/process/task_queues.js:98:32)"]}

followed by:

[ERROR] [1591130035553] LAMBDA_RUNTIME Failed to post handler success response. Http response code: 403.

Here’s my code:

const faunadb = require('faunadb'); 
const q = faunadb.query;

exports.handler = async (event, context, callback) => {
  try {
    const client = new faunadb.Client({
      secret: process.env.SECRET
    });

    const reservation = JSON.parse(event.body);
    let reservationBlockRef =
      reservation.reservationBlock?.reservationBlock?.ref?.['@ref']?.id;

    // double check here to see if a reservation block exists
    if (!reservationBlockRef) {
      const { data } = await client.query(
        // query
      );

      for (let block of data) {
        if (
          block.data.start_time === reservation.start &&
          block.data.end_time === reservation.end
        ) {
          reservationBlockRef = block.ref.id;
        }
      }
    }

    // if it really doesn't exist at this point, we're creating one
    if (!reservationBlockRef) {
      const response = await client.query(
      //  query
      );
      return new Promise(resolve =>
        resolve({
          headers: {
            'Access-Control-Allow-Origin': '*'
          },
          statusCode: 200,
          body: JSON.stringify(response)
        })
      );
    }

    const res = client.query(
    // query
    );
    return new Promise(resolve =>
      resolve({
        headers: {
          'Access-Control-Allow-Origin': '*'
        },
        statusCode: 200,
        body: JSON.stringify(res)
      })
    );
  } catch (error) {
    return new Promise(resolve =>
      resolve({
        headers: {
          'Access-Control-Allow-Origin': '*'
        },
        statusCode: 400,
        body: JSON.stringify(error)
      })
    );
  }
};

Does anyone know what I’m doing wrong?

Hi,

First, when using an async function handler, you won’t need to define a callback function arg. That said, inside your handler function, you should be returning an object and not a promise like you are doing now. Just:

return {
  headers: {},
  statuscode: 200,
  body: JSON.stringify(res)
}

Let me know how it goes.

Hey Dennis,

Thanks for getting back to me, I really appreciate it!

Unfortunately, that solution was actually the first thing that I tried. However, I did have the callback argument defined. Not sure if that changes anything about how netlify builds the lambda functions.

I was able to eventually fix the second two errors with the following code,
it does seem weird to me to have to do it this way though. Maybe you have some insight?

exports.handler = (event, context, callback) => {
  main(event)
    .then(response => {
      console.log(response);
      callback(null, response);
    })
    .catch(error => {
      console.log(error);
    });
};

async function main(event, callback) {
  try {
    const client = new faunadb.Client({
      secret: process.env.SECRET
    });

    const reservation = JSON.parse(event.body);
    let reservationBlockRef = null;

    if (reservation.reservationBlock) {
      reservationBlockRef =
        reservation.reservationBlock.reservationBlock.ref['@ref'].id;
    }

    // double check here to see if a reservation block exists
    if (!reservationBlockRef) {
      const { data } = await client.query(
        //query
      );

      for (let block of data) {
        if (
          block.data.start_time === reservation.start &&
          block.data.end_time === reservation.end
        ) {
          reservationBlockRef = block.ref.id;
        }
      }
    }

    // if it really doesn't exist at this point, we're creating one
    if (!reservationBlockRef) {
      // first create the block then create the reservation and add it to the block
      const response = await client.query(
        //query
      );
      return new Promise(resolve => {
        resolve({
          headers: {
            'Access-Control-Allow-Origin': '*'
          },
          statusCode: 200,
          body: JSON.stringify(response)
        });
      });
    }

    // if the request was sent with a block, or we found a block previously
    const res = client.query(
          // query
    );
    return new Promise(resolve => {
      resolve({
        headers: {
          'Access-Control-Allow-Origin': '*'
        },
        statusCode: 200,
        body: JSON.stringify(res)
      });
    });
  } catch (error) {
    return new Promise(resolve => {
      resolve({
        headers: {
          'Access-Control-Allow-Origin': '*'
        },
        statusCode: 200,
        body: JSON.stringify(error)
      });
    });
  }
}

This did not fix the first error though, the buffer depreciation warning still pops up from time to time in both development and production. I checked the built function, and it seems to contain Buffer(). I’m using netlify-lambda v 1.6.3 and wondering if it has to do with that?

Hi @danem, With regards to the Promise, I think your new code allows the Promise to resolve inside the handler function, while the initial function returns a Promise when the handler function resolves.

Regarding the netlify-lambda, have you tried not bundling your function using netlify-lambda and just letting the buildbot use ‘zip-it-and-ship-it’ zip your function up? You’ll probably need to run npm i inside your function folder, like I did here: function-deploy-test/package.json at master · netlify/function-deploy-test · GitHub to make sure your dependencies installed.

Otherwise, the Buffer() warning is just that. A warning and shouldn’t prevent your function from functioning (pun slightly intended).