Search code examples
amazon-web-servicesamazon-dynamodbamazon-lex

AWS Lex : An error has occurred: Invalid Lambda Response


I am trying to save the values gathered with Amazon Lex into DynamoDB. I made (or copied and modified) a Lambda function, which obviously does not work, but I really don't understand why. This is the error I get from Amazon Lex : "An error has occurred: Invalid Lambda Response: Received error response from Lambda: Handled"

Everything else works fine, I solved a permission issue, and other errors I got.

When I get that error, the dialog is at state :

{
   "dialogState": "ElicitSlot",
   "intentName": "MCQ_A",
   "message": "What is a black and white horse",
   "messageFormat": "PlainText",
   "responseCard": null,
   "sessionAttributes": {},
   "slotToElicit": "QB",
   "slots": {
       "QA": "4",
       "QB": null,
       "Session": "444"
   }
}

// Here is my Lambda function. It is written in javascript, which I just discovered, and which I am absolutely not comfortable with ^^'

console.log('Loading event');
var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
var tableName = "MCQ";

// Close dialog with the customer, reporting fulfillmentState of Failed or Fulfilled
function close(session_attributes, m) {
    let callback_obj = {
        sessionAttributes: session_attributes,
        dialogAction: {
            type: 'Close',
            fulfillmentState: "Fulfilled",
            message: m,
        }
    }
    return callback_obj;
}

function storeRegistration(intent, callback) {

    let userInfo = {};

    // store every slot we received as part of registration
    Object.keys(intent.slots).forEach((item) => {
        console.log(item)
        userInfo[item] = {"S": intent.slots[item]};
    });

    dynamodb.putItem({
        "TableName": tableName,
        "Item" : userInfo
    }, function(err, data) {
        if (err) {
            console.log('Failure storing user info');
            console.log(err);
            callback(close(intent.sessionAttributes, {contentType: 'PlainText', content: "I am sorry, but something went wrong. Please try again."}));
        } else {
            console.log("Successfully Stored UserInfo");
            callback(close(intent.sessionAttributes, {contentType: 'PlainText', content: "Thank you for attending the MCQ."}));
        }
    });
}

// --------------- Main handler -----------------------

// Route the incoming request based on intent.
// The JSON body of the request is provided in the event slot.
exports.handler = (event, context, callback) => {
    console.log(event);
    try {
        storeRegistration(event, (response) => {callback(null, response)});
    } catch (err) {
        callback(err);
    }
};

Do you have any idea what's going on ? :) Thank you very much in advance !!


Solution

  • I FOUND A SOLUTION :

    I gave up my function and took the blueprint by AWS called lex-order-flowers-python. It works out of the box with the Lex blueprint OrderFlowers. I just had to adapt it to my work, and add the DynamoDB part.

    Make sure that your Item is in the good format, with the value type specified ('S' for a String)

    put_item(
        TableName = 'myTableName',
        Item = {
            'key1': {'S': 'value1'}
            'key2': {'S': 'value2'}
        })
    

    So I made this :

    userInfo = {}
    for key, value in intent_request['currentIntent']["slots"].items() :
        userInfo[key] = {'S': value}
    
    logger.debug(userInfo)
    
    dynamodb = boto3.client('dynamodb')
    dynamodb.put_item(TableName='MCQ', Item=userInfo)