aws / aws/aws-cdk

stepfunctions: Default Choice state not created when using afterwards with includeOtherwise

Open
#20,685 9 comments 2 reactions 0 assignees View on GitHub
@aws-cdk/aws-stepfunctions bug effort/medium p3
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

It is not possible to use nested Choice states that only define single `.when()` cases each and utilise `.afterwards({ includeOtherwise: true })` for the Default flow, because the nested Default branch is not created.

The state machine would approximate the following algorithm:
```
if (firstFlag) {
// Do Something
if (secondFlag) {
// Failure
}
}
// All Successful
```

### Expected Behavior

The inner `Choice` should have a `Default` transition to `All Successful`:
```json
{
"StartAt": "First Choice",
"States": {
"First Choice": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.firstFlag",
"BooleanEquals": false,
"Next": "Do Something"
}
],
"Default": "All Successful"
},
"All Successful": {
"Type": "Succeed"
},
"Do Something": {
"Type": "Pass",
"Next": "Second Choice"
},
"Second Choice": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.secondFlag",
"BooleanEquals": false,
"Next": "Failure"
}
],
"Default": "All Successful"
},
"Failure": {
"Type": "Fail"
}
}
}
```

![expected-inner-default](https://user-images.githubusercontent.com/1573997/172829412-dfdffd52-01d7-45d8-98a1-fb842977b648.png)

### Current Behavior

The inner `Choice` does not have a `Default` transition created:
```json
{
"StartAt": "First Choice",
"States": {
"First Choice": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.firstFlag",
"BooleanEquals": false,
"Next": "Do Something"
}
],
"Default": "All Successful"
},
"All Successful": {
"Type": "Succeed"
},
"Do Something": {
"Type": "Pass",
"Next": "Second Choice"
},
"Second Choice": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.secondFlag",
"BooleanEquals": false,
"Next": "Failure"
}
]
},
"Failure": {
"Type": "Fail"
}
}
}
```

![no-inner-default](https://user-images.githubusercontent.com/1573997/172830354-09609a4b-3064-49d6-b664-3c2275b18180.png)

### Reproduction Steps

Create the step machine using the following CDK:

```typescript
new sfn.Choice(stack, "First Choice")
.when(
sfn.Condition.booleanEquals("$.firstFlag", false),
new sfn.Pass(stack, "Do Something").next(
new sfn.Choice(stack, "Second Choice")
.when(sfn.Condition.booleanEquals("$.secondFlag", false), new sfn.Fail(stack, "Failure"))
.afterwards({ includeOtherwise: true })
)
)
.afterwards({ includeOtherwise: true })
.next(new sfn.Succeed(stack, "All Successful"))
```

Execute the step machine using the following input to trigger the missing Default branch:

```json
{
"firstFlag": false,
"secondFlag": true
}
```

### Possible Solution

_No response_

### Additional Information/Context

This could be worked around by providing a dummy `Pass` state after `.afterwards()` definition:

```typescript
new sfn.Choice(stack, "First Choice")
.when(
sfn.Condition.booleanEquals("$.firstFlag", false),
new sfn.Pass(stack, "Do Something").next(
new sfn.Choice(stack, "Second Choice")
.when(sfn.Condition.booleanEquals("$.secondFlag", false), new sfn.Fail(stack, "Failure"))
.afterwards({ includeOtherwise: true })
.next(new sfn.Pass(stack, "Unnecessary Do-Nothing Pass for Default"))
)
)
.afterwards({ includeOtherwise: true })
.next(new sfn.Succeed(stack, "All Successful"))
```

![workaround-default](https://user-images.githubusercontent.com/1573997/172831193-5b32a513-b3c9-4168-8da3-f809a1f9308e.png)

### CDK CLI Version

1.159.0

### Framework Version

_No response_

### Node.js Version

16.13.2

### OS

MacOS

### Language

Typescript

### Language Version

4.5.5

### Other information

Might be related to issue aws/aws-cdk#16210 and discussion aws/aws-cdk#19718.

Contributor guide

Open the contributing guide

Research direction

Start with the TypeScript reproduction in the issue and inspect the generated AWS Step Functions state machine for nested Choice states using afterwards({ includeOtherwise: true }). Compare the inner Choice with the expected JSON and the dummy-Pass workaround. Done means the inner Choice receives a Default transition to All Successful without requiring an unnecessary Pass state.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.