16

I'm using step functions on AWS. Consider the state machine made up of lambdas:

"StartAt": "Metadata",
              "States": {
                    "Metadata": {
                    "Type": "Task",
                    "Resource": "${metadataArn}",
                    "Next": "StoreMetadata",
                    "Retry" : [
                            {
                                "ErrorEquals": [ "States.All" ],
                                "IntervalSeconds": 2,
                                "MaxAttempts": 3
                            }
                    ],
                    "Catch": [
                        {
                            "ErrorEquals": [ "States.All" ],
                            "Next": "ErrorHandler"
                        }
                    ]
                  } ...
                      ...

How can I pass particular data to the "ErrorHandler". For example, the step that failed, maybe a piece of data. I'm using nodejs but can extrapolate to any runtime.

For example in node we might have a lambda where:

module.exports.handler = async input => {
  const ids = JSON.parse(input).ids
  // try to read in data for ids.
  // read fails / throws exception
}

How can I have the error handler get the array of ids so I can mark them as failed? if this "ErrorHandler" is the catch for multiple steps how can I have it know which steps failed?

Zachscs
  • 3,353
  • 7
  • 27
  • 52

3 Answers3

34

I found an answer, you can use ResultPath to pass the original input along with the error. I suppose I will include the step as a property in all inputs so that I can know what step failed. See the docs for an explanation. Essentially to accomplish this you would just add the ResultPath property like so:

"Catch": [
  {
    "ErrorEquals": [ "States.All" ],
    "Next": "ErrorHandler"
    "ResultPath": "$.error"
  }
]
Zachscs
  • 3,353
  • 7
  • 27
  • 52
5

I wanted to add to @Zachscs answer that you need to be careful when doing "Catch" on "Type": "Map", as this is and doing "ResultPath": "$.error", will throw:

Unable to apply step "error" to input [...]

This makes sense, as the input is an array. You solve it by adding a simple zero-based index to error like this:

"Type": "Map",
"Next": "Finish",
"Catch": [
  {
    "ErrorEquals": [ "States.All" ],
    "Next": "ErrorHandler",
    "Comment": "Note the $[0] down below",
    "ResultPath": "$[0].error"
  }
]

This will append it to the second index of the array $[1].error

Jose A
  • 10,053
  • 11
  • 75
  • 108
1

And for those who use AWS CDK to create step function:

yourTask.addCatch(sendFailureNotify, {
  resultPath: '$.error'
});

where sendFailureNotify is your lambda. And the props resultPath? is where you set the $.error

/**
 * Error handler details.
 */
export interface CatchProps {
    /**
     * Errors to recover from by going to the given state.
     *
     * A list of error strings to retry, which can be either predefined errors
     * (for example Errors.NoChoiceMatched) or a self-defined error.
     *
     * @default All errors
     */
    readonly errors?: string[];
    /**
     * JSONPath expression to indicate where to inject the error data.
     *
     * May also be the special value DISCARD, which will cause the error
     * data to be discarded.
     *
     * @default $
     */
    readonly resultPath?: string;
}
Granit
  • 188
  • 1
  • 11