Search code examples
flaskalexa-skills-kitflask-ask

400 Bad Request error on a LaunchRequest with flask-ask


I'm trying to debug a small Alexa skill that is build with the flask-ask framework. My problem is that I keep getting a 400 error on a simple LaunchRequest. The relevant intent function is this:

@ASK.launch
def launch():
    """Welcome & ask for users intent."""
    APP.logger.debug('LAUNCHING SESSION')
    return question(render_template('welcome'))

When I run the server locally in debug mode (tunneled through ngrok) and make a simple launch request ("start my_skills_name") flask logs two requests:

$ python main.py app --run
INFO:werkzeug: * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
INFO:werkzeug:127.0.0.1 - - [18/Feb/2018 12:47:43] "POST / HTTP/1.1" 400 -
INFO:werkzeug:127.0.0.1 - - [18/Feb/2018 12:47:44] "POST / HTTP/1.1" 200 -

The logging message from the intent function is never shown.

When I deploy the skill with zappa and do a zappa tail I get to see the second request (SessionEndedRequest). This returns a 200 status code, but does seem to produce some exception:

"request":{
    "type":"SessionEndedRequest",
    "requestId":"<1234>",
    "timestamp":"2018-02-18T11:54:46Z",
    "locale":"de-DE",
    "reason":"ERROR",
    "error":{
        "type":"INVALID_RESPONSE",
        "message":"An exception occurred while dispatching the request to the skill."
     }
}

The function for this request is again very simple:

@ASK.session_ended
def session_ended():
    APP.logger.debug('ENDING SESSION')
    return statement('bye')

The logging message is not shown, and the error stays the same even if I remove that function and don't handle SessionEndedRequests at all.

I'm a bit out of ideas what could be happening here. The requests do reach my server, indicating that the skill itself is configured correctly. It looks like they somehow don't get routed to the proper intent functions, yet since I'm completely relying on the ask.intent decorator for that I have no idea how to fix this. Could someone give me a hint?


Solution

  • Answering myself because I have figured it out:

    I was running the APP from the packages __init__.py file, while keeping the intent functions in a separate intents.py in the same package. For that to work one has to import the intent module into the init file, but only after the APP object was created. That means mypackage/__init__.py has to look like this:

    from flask import Flask
    from flask_ask import Ask
    
    APP = Flask(__name__)
    ASK = Ask(APP, '/')
    
    from my_package import intents  # importing my_package/intents.py
    

    A more detailed explanation can be found in the flask documentation for larger applications.