Matthew Pans
Matthew Pans

Reputation: 783

AWS Step Function workflow is showing failed status when excuting

I am following this tutorial for creating a sample workflow with AWS Step Functions and AWS Lambda. I have done everything as per the blog, but when I run it is showing failed status at the "Is Case Resolved" stage.

Screenshot: https://i.sstatic.net/ebmbb.png

I have done like below:

Step1: Created a role in AWS Management Console and copied the Role ARN value.

Step2: Created a new State Machine with the ASL code provided in the blog and added the Role ARN value.

Step3: Created all the 5 AWS Lambda Functions

Step4: Edited the state Machine and added the Resource value of the Lambda function.

Step5: Executed the workflow with the below code:

{
    "inputCaseID": "001"
}

My ASL code in state machine:

    {
      "Comment": "A simple AWS Step Functions state machine that automates a call center support session.",
      "StartAt": "Open Case",
      "States": {
        "Open Case": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:us-east-2:AccountId:function:OpenCaseFunction",
          "Next": "Assign Case"
        }, 
        "Assign Case": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:us-east-2:AccountId:function:AssignCaseFunction",
          "Next": "Work on Case"
        },
        "Work on Case": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:us-east-2:AccountId:function:WorkOnCaseFunction",
          "Next": "Is Case Resolved"
        },
        "Is Case Resolved": {
            "Type" : "Choice",
            "Choices": [ 
              {
                "Variable": "$.Status",
                "NumericEquals": 1,
                "Next": "Close Case"
              },
              {
                "Variable": "$.Status",
                "NumericEquals": 0,
                "Next": "Escalate Case"
              }
          ]
        },
         "Close Case": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:us-east-2:AccountId:function:CloseCaseFunction",
          "End": true
        },
        "Escalate Case": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:us-east-2:AccountId:function:EscalateCaseFunction",
          "Next": "Fail"
        },
        "Fail": {
          "Type": "Fail",
          "Cause": "Engage Tier 2 Support."    }   
      }
    }

Error showing:

{
  "error": "States.Runtime",
  "cause": "An error occurred while executing the state 'Is Case Resolved' (entered at the event id #17). Invalid path '$.Status': The choice state's condition path references an invalid value."
}

OpenCaseFunction

exports.handler = (event, context, callback) => {
    // Create a support case using the input as the case ID, then return a confirmation message   
   var myCaseID = event.inputCaseID;
   var myMessage = "Case " + myCaseID + ": opened...";   
   var result = {Case: myCaseID, Message: myMessage};
   callback(null, result);    
};

AssignCaseFunction

exports.handler = (event, context, callback) => {    
    // Assign the support case and update the status message    
    var myCaseID = event.Case;    
    var myMessage = event.Message + "assigned...";    
    var result = {Case: myCaseID, Message: myMessage};
    callback(null, result);        
};

WorkOnCaseFunction

exports.handler = (event, context, callback) => {    
    // Generate a random number to determine whether the support case has been resolved, then return that value along with the updated message.
    var min = 0;
    var max = 1;    
    var myCaseStatus = Math.floor(Math.random() * (max - min + 1)) + min;
    var myCaseID = event.Case;
    var myMessage = event.Message;
    if (myCaseStatus == 1) {
        // Support case has been resolved    
        myMessage = myMessage + "resolved...";
    } else if (myCaseStatus == 0) {
        // Support case is still open
        myMessage = myMessage + "unresolved...";
    } 
    var result = {Case: myCaseID, Status : myCaseStatus, Message: myMessage};
    callback(null, result); 
};

EscalateCaseFunction

exports.handler = (event, context, callback) => {    
    // Escalate the support case 
    var myCaseID = event.Case;    
    var myCaseStatus = event.Status;    
    var myMessage = event.Message + "escalating.";    
    var result = {Case: myCaseID, Status : myCaseStatus, Message: myMessage};
    callback(null, result);
};

CloseCaseFunction

exports.handler = (event, context, callback) => { 
    // Close the support case    
    var myCaseStatus = event.Status;    
    var myCaseID = event.Case;    
    var myMessage = event.Message + "closed.";    
    var result = {Case: myCaseID, Status : myCaseStatus, Message: myMessage};
    callback(null, result);
};

What I am missing in this?

Upvotes: 0

Views: 3707

Answers (2)

samtoddler
samtoddler

Reputation: 9605

The named WorkOnCaseFunction is not producing correct output which should be something like below structure.

{ Case: '001', Status: 0, Message: 'hellounresolved...' }

It is consumed by the choice state which tries to fetch Status by using jsonpath $.Status.

If it is not present then it errors out and cancels the further execution of the statemachine.

For example:

Below is my state machine without DefaultState for Choice State, Either Fail or Success depending on the output produced by function:mytestfunction which can be either 0 or 1.

{
  "Comment": "An example of the Amazon States Language using a choice state.",
  "StartAt": "FirstState",
  "States": {
    "FirstState": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:eu-central-1:1234567890:function:mytestfunction",
      "Next": "ChoiceState"
    },
    "ChoiceState": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.Status",
          "NumericEquals": 1,
          "Next": "Success"
        },
        {
          "Variable": "$.Status",
          "NumericEquals": 0,
          "Next": "Failed"
        }
      ]
    },
    "Success": {
      "Type": "Pass",
      "Comment": "Success",
      "End": true
    },
    "Failed": {
      "Type": "Pass",
      "Comment": "Failed",
      "End": true
    }
  }
}

function:mytestfunction code

exports.handler = (event, context, callback) => {    
    // Generate a random number to determine whether the support case has been resolved, then return that value along with the updated message.
    var min = 0;
    var max = 1;    
    var myCaseStatus = Math.floor(Math.random() * (max - min + 1)) + min;
    var myCaseID = "001";
    var myMessage = "hello";
    if (myCaseStatus == 1) {
        // Support case has been resolved    
        myMessage = myMessage + "resolved...";
    } else if (myCaseStatus == 0) {
        // Support case is still open
        myMessage = myMessage + "unresolved...";
    } 
    var result = {Case: myCaseID, Status : myCaseStatus, Message: myMessage};
    console.log('result: %s', result);
    callback(null, result); 
};

I just added a log message what is being returned to stepfunction, plus just for testing I made message and case static.

That gives me the output like

enter image description here

Then this output from lambda is being consumed by Choice state and it tries to fetch just Status out of the following json which is produced by function:mytestfunction

{ Case: '001', Status: 0, Message: 'hellounresolved...' }

enter image description here

Now you can see what is going wrong with the lambda named WorkOnCaseFunction. It is not producing the output in the above format and your state machine is failing.

Upvotes: 1

smac2020
smac2020

Reputation: 10704

Try this one - it works perfectly and been tested many times.

enter image description here

Its similar - but the difference is the Lambda functions were written using the Java run-time API. It also show you how to invoke other AWS Services - such as Amazon DynamoDB - from a Lambda function:

Create AWS serverless workflows by using the AWS SDK for Java

Upvotes: 0

Related Questions