question

t0mhan avatar image
t0mhan asked

Issue calling intent from another intent

const helper = require("../helper/helper-functions");
const data = require("../helper/data");
const HotelBookingIntent_Handler = require("../handlers/HotelBookingIntent_Handler");
const GetHotelorRegionName_Handler = require("../handlers/GetHotelorRegionName_Handler");

const GetTravelDates_Handler =  {
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'IntentRequest' && request.intent.name === 'GetTravelDates' ;
    },
    handle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        const responseBuilder = handlerInput.responseBuilder;
        let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();

        return GetHotelorRegionName_Handler.handle(handlerInput);
    },
};

module.exports = GetTravelDates_Handler;
<br>

Both the intents required one slot each to fullfil the intent. I am getting this error,

`{
    "errorMessage":"errorHandler.canHandle is not a function",
    "errorType":"TypeError",
    "stackTrace": [
        "DefaultErrorMapper.<anonymous> (/var/task/node_modules/ask-sdk-core/lib/dispatcher/error/DefaultErrorMapper.js:74:59)",
        "step (/var/task/node_modules/ask-sdk-core/lib/dispatcher/error/DefaultErrorMapper.js:44:23)",
        "Object.next (/var/task/node_modules/ask-sdk-core/lib/dispatcher/error/DefaultErrorMapper.js:25:53)",
        "/var/task/node_modules/ask-sdk-core/lib/dispatcher/error/DefaultErrorMapper.js:19:71",
        "new Promise (<anonymous>)",
        "__awaiter (/var/task/node_modules/ask-sdk-core/lib/dispatcher/error/DefaultErrorMapper.js:15:12)",
        "DefaultErrorMapper.getErrorHandler (/var/task/node_modules/ask-sdk-core/lib/dispatcher/error/DefaultErrorMapper.js:64:16)",
        "DefaultRequestDispatcher.<anonymous> (/var/task/node_modules/ask-sdk-core/lib/dispatcher/DefaultRequestDispatcher.js:178:63)",
        "step (/var/task/node_modules/ask-sdk-core/lib/dispatcher/DefaultRequestDispatcher.js:44:23)",
        "Object.next (/var/task/node_modules/ask-sdk-core/lib/dispatcher/DefaultRequestDispatcher.js:25:53)"
    ]
}`
alexa skills kitlambdaintentsslotsintent request history
3 comments
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

What I see from the error: 'errorHandler.canHandle is not a function', means that there is a problem with errorHandler canHandle function. Of course there is a problem in the code in the first place, because it is being invoked, but first fix errorHandler canHandle function, then print out the error there and work from there. It should give you more details what is wrong. Example error handler:

const ErrorHandler: ErrorHandler = {
  canHandle(handlerInput: HandlerInput, error: Error): boolean {
    return true
  },
  handle(handlerInput: HandlerInput, error: Error): Response {
    console.log(`Error handled: ${JSON.stringify(error, null, 2)}`)
    return responseBuilder
      .speak('Woooops')
      .withShouldEndSession(true)
      .getResponse()
  },
}

Also don't forget that error handler is registered using '.addErrorHandlers()' function not, 'addRequestHandlers()' function.

0 Likes 0 ·

@RokasV

Thank you for your response, I have registered ErrorHandler using '.addErrorHandlers(). This is my error handler:

const ErrorHandler = { 
  canHandle() { 
    return true; 
 }, 
  handle(handlerInput, error) { 
    const request = handlerInput.requestEnvelope.request; 
    console.log(`Error handled: ${error.message}`); 
    console.log(`Original Request was: ${JSON.stringify(request, null, 2)}`); 
    return handlerInput.responseBuilder 
      .speak(`Sorry, your skill got this error. ${error.message} `) 
      .reprompt(`Sorry, your skill got this error. ${error.message} `) 
     .getResponse();
  } 
};
 module.export = ErrorHandler;
0 Likes 0 ·

Okay, so now when you run your skill, what error is printed out?

I see you also asked if calling canHandle() from one intent to another is the correct way and it isn't. canHandle() returns only boolean if that handler could handle that request. In order to call another handler you should call handle() and pass current intent handlerInput so it should look like this:

return HandlerName.handle(handlerInput)

Don't forget to add return to pass control to another intent.

0 Likes 0 ·

1 Answer

Jamie Grossman avatar image
Jamie Grossman answered

I don't think the SDK works like that. You can't call the 'canHandle' part of the object; there are a few ways to get around this, but you could always just put the code in the canHandle part in it's own function and call it through that (passing in any parameters you need).

4 comments
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

@Jamie@Amazon could you please suggest some workaround, I have separated my intents in different files and exporting like module.exports = ErrorHandler to add in index.js and call intents from another intent.

From GetTravelDates_Handler I am calling canHandle of GetHotelorRegionName which is in another file. Is this the right way? If not please suggest the correct way to do it.

0 Likes 0 ·

As suggested above, why can't you take whatever code you were calling in the canHandle, and put it in it's own function? You could then call the function from the canHandle, and from any other canHandle from another handler without issue.

0 Likes 0 ·
t0mhan avatar image t0mhan Jamie Grossman ♦♦ ·
@Jamie@Amazon

I got what you are saying. But it doesnot solve my roblem.

I will explain my issue in detail.

We are trying to make hotel booking skill. It requrires multiple inputs(Hotel name, check-in-date, checkout-date, number of adults etc).
Right now the problem is, after collecting all the four slots, control goes to Lambda function for validating these values.

What I want is, to validate each values when they are provided by user. For this I have devided main intent into smaller intents like GetHotelName, GetAdults, GetTravellingDates etc so that after filling slot control goes to Lambda funtion for validation.

I am starting with GetHotelName, validated data and from their trying to call GetAdults intent like this:

return GetTravelDates_Handler.handle(handlerInput);

But I am getting error 'Cannot read property 'heardAs' of undefined' because the handlerInput is of GetHotelName.

So my question is how can I call second intent from first intent then from second to third ?

0 Likes 0 ·
Show more comments