Is there any way to catch AWS lambda timed out error in code level?

Update:

Use the built-in Promise.race() function instead:


module.exports.myFunction = async (event) => {

  // your real task
  const task = new Promise((resolve) => {
    setTimeout(() => resolve({ statusCode: 200, message: 'Task finished.' }), 1000);
  })

  // add a new "task": timeout 
  const timeout = new Promise((resolve) => {
    setTimeout(() => resolve({ statusCode: 504, message: 'Sorry, your task timed out!' }), 200);
  })
  
  // start them synchronously
  const res = await Promise.race([task, timeout]);
  return res;
};

I would like to share my solution here:
Let's say I have a Lambda handler function and its timeout limit I set was 15 mins. Inside this function, I have an async function named work() which may takes longer that 15 mins.

To catch the timeout error from Lambda, my way is:
I create a new async function named timeout(), and this function simply return after 14.9 mins. And I let work() and timeout() functions start at the same time, if work() can finish in 14.9 mins, then work() returns earlier that timeout(), otherwise, timeout() returns earlier.
You can see it easier with this diagram:

enter image description here

And this is just what race() operator does from rxjs.

Here is the code that implement this idea by using rxjs:

module.exports.myFunction = async (event) => {
  function task() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('finished!');
      }, 15 * 60 * 1000);
    });
  }

  function timeout() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('timeout!');
      }, 14.9 * 60 * 1000);
    });
  }


  const res = await new Promise((resolve, reject) => {
    race(from(task()), from(timeout()))
      .subscribe(msg => {
        resolve(msg);
      })
  });

  return { res };
};

While the lambda environment doesn't fire a "timing out" event, you can do this yourself fairly trivially.

Each language has a function exposed by the context object to get the remaining time in milliseconds.

You can use that, in tandem with the timer functionality of whatever language you're using to ensure you get notified before timeout.

For example (node):

function handler(event, context, callback) {
  const timer = setTimeout(() => {
    console.log("oh no i'm going to timeout in 3 seconds!");
    // &c.
  }, context.getRemainingTimeInMillis() - 3 * 1000);
  try {
    // rest of code...
  } finally {
    clearTimeout(timer);
  }
  callback(null, result);
}