(aws-stepfunctions-tasks): DynamoAttributeValue.fromNumber() breaks when passed a JsonPath
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
`DynamoAttributeValue.fromNumber()` synths incorrectly when passed a `JsonPath.numberAt()` for getting a number from a step's input.
Example:
```ts
DynamoAttributeValue.fromNumber(JsonPath.numberAt('$.viewCount')
```
Synths as:
```
{\":viewCount\":{\"N\":\"-1.888154589708819e+289\"}}
```
### Reproduction Steps
#### 1. Deploy ProblemStack
```ts
import { Table, AttributeType, BillingMode } from '@aws-cdk/aws-dynamodb';
import { LogGroup, RetentionDays } from '@aws-cdk/aws-logs';
import { StateMachine, Chain, StateMachineType, LogLevel, JsonPath } from '@aws-cdk/aws-stepfunctions';
import { DynamoUpdateItem, DynamoAttributeValue, DynamoReturnValues } from '@aws-cdk/aws-stepfunctions-tasks';
import { Stack, Construct, StackProps, RemovalPolicy } from '@aws-cdk/core';
export class ProblemStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps = {}) {
super(scope, id, props);
const table = new Table(this, 'MyTable', {
partitionKey: { name: 'id', type: AttributeType.STRING },
billingMode: BillingMode.PAY_PER_REQUEST,
removalPolicy: RemovalPolicy.DESTROY,
});
const updateViewCount = new DynamoUpdateItem(this, 'PutVideosViewCount', {
table: table,
key: {
id: DynamoAttributeValue.fromString(JsonPath.stringAt('$.id')),
},
returnValues: DynamoReturnValues.ALL_NEW,
updateExpression: 'SET viewCount = :viewCount',
expressionAttributeValues: {
':viewCount': DynamoAttributeValue.fromNumber(JsonPath.numberAt('$.viewCount')),
},
});
const main = Chain.start(updateViewCount);
const stateMachineLogs = new LogGroup(this, 'MyStateMachineLogGroup', {
retention: RetentionDays.THREE_MONTHS,
});
new StateMachine(this, 'MyStateMachine', {
definition: main,
stateMachineType: StateMachineType.STANDARD,
tracingEnabled: true,
logs: {
destination: stateMachineLogs,
includeExecutionData: true,
level: LogLevel.ALL,
},
});
}
}
```
#### 2. Insert a record into the DynamoDB table
```json
{
"id": "foo",
"viewCount": 10
}
```
#### 3. Start state machine execution with event
```json
{
"id": "foo",
"viewCount": 1234
}
```
### What did you expect to happen?
The template should synth to extract the number from the input and then update the record in the db.
### What actually happened?
The execution fails with the error:
```
"ExpressionAttributeValues contains invalid value: Number overflow. Attempting to store a number with magnitude larger than supported range for key :viewCount (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: c056d945-3aa5-484e-8c64-eb75b9b9041c; Proxy: null)
```
This is because the template was synthed as:
```
\"ExpressionAttributeValues\":{\":viewCount\":{\"N\":\"-1.888154589708819e+289\"}}
```
### Environment
- **CDK CLI Version :** 1.83.0
- **Framework Version:**
- **Node.js Version:** v12.19.0
- **OS :** Linux
- **Language (Version):** TypeScript Version 4.0.5
### Other
---
This is :bug: Bug Report
Contributor guide
Research direction
Trace DynamoAttributeValue.fromNumber() and JsonPath.numberAt() in the aws-stepfunctions-tasks implementation, then find the related synthesis or task tests. Reproduce the supplied stack and verify that a JsonPath number produces a valid runtime DynamoDB value instead of a huge literal and that the update succeeds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- backend, cloud
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100