3

I'm trying to log errors in an alexa skill that runs in a Lambda function, but no matter what I try, errors somehow get through my try/catch blocks without being logged.

This is my index.js:

const Alexa = require('ask-sdk-core');

try {
  const handlers = require('./handlers');

  const wrappedHandlers = handlers.map(handler => ({
    ...handler,
    async handle(handlerInput) {
      try {
        console.log(`Running handler ${handler.name}`, JSON.stringify(handlerInput, null, 2));
        const response = await handler.handle(handlerInput);
        console.log(`Successfully ran handler ${handler.name}`, JSON.stringify(response, null, 2));
        return response;
      } catch(error) {
        console.log(`Failed to run handler ${handler.name}`, error.stack);
        throw error;
      }
    },
  }));

  exports.handler = Alexa.SkillBuilders
    .custom()
    .addRequestHandlers(...wrappedHandlers)
    .addErrorHandlers(require('./handlers/error'))
    .lambda();
} catch(error) {
  console.log('Fatal initialization error', error);
  exports.handler = Alexa.SkillBuilders
    .custom()
    .addRequestHandlers({
      canHandle() { return true; },
      handle(handlerInput) {
        return handlerInput.responseBuilder
          .speak(`Initialization error`, error.stack);
      },
    })
    .lambda();
}

The top-level try/catch should catch any errors thrown during require('./handlers'). I've observed this working in the past catching syntax errors in my handlers.

I'm also wrapping every handler's handle function in a try/catch (see wrappedHandlers). My error handler also logs any errors it sees:

// handlers/error.js
module.exports = {
  canHandle() { return true; },

  handle(handlerInput, error) {
    console.log(`Error handled: ${error.stack}`);

    // During tests, include the error in the response
    if(process.env['NODE_ENV'] === 'test') {
      const { attributesManager } = handlerInput;
      const sessionAttributes = attributesManager.getSessionAttributes();
      sessionAttributes.error = error;
      attributesManager.setSessionAttributes(sessionAttributes);
    }

    const message = error && error.speachMessage || `Sorry, I can't understand the command. Please say again. ${error.stack}`;
    return handlerInput.responseBuilder
      .speak(message)
      .reprompt(message)
      .getResponse();
  },
};

Despite all of this, the Alexa simulator is spitting out [Error]: An unexpected error occurred., but the cloudwatch logs don't contain any errors or failed requests. How is this possible?

SimpleJ
  • 13,812
  • 13
  • 53
  • 93
  • `speachMessage` -> `speechMessage`? – Bergi Dec 19 '18 at 06:37
  • That is a typo, but it's consistent throughout, so I don't think it's causing the issue. Though it would make sense that an error being thrown in the error handler would cause this issue so I'll test that a bit more. – SimpleJ Dec 19 '18 at 16:55

1 Answers1

0

I'm also experiencing this problem and I've got a function which is throwing with a lambda 502 bad gateway, the cloudwatch log entry contains

Invoke Error {"errorType":"UnauthorizedError","errorMessage":"Forbidden","name":"UnauthorizedError","stack":["UnauthorizedError: Forbidden"," at /var/task/ApiServerClass.js:57:27"," at processTicksAndRejections (internal/process/task_queues.js:97:5)"," at async module.exports.me (/var/task/ApiServerClass.js:68:43)"," at async module.exports.run (/var/task/ApplicationClass.js:42:22)"]}

But wrapped around that entire function is a try/catch

It's as if throwing an exception immediately causes lambda to quit and all your exception handling is ignored. But when running local tests through mocha. The exceptions are respected

Narendra Prasath
  • 1,501
  • 1
  • 10
  • 20
Christopher Thomas
  • 4,424
  • 4
  • 34
  • 49