Closed
Description
Is there an existing issue for this?
- I have searched the existing issues
Current Behavior
Hi LocalStack team,
I'm encountering an issue when using Step Functions to query a DynamoDB table. Specifically, when the DynamoDB item includes an attribute of type Map, the query fails with the following error:
'MapShape' object has no attribute 'members'
Expected Behavior
The Step Function should successfully query the DynamoDB table and handle items with Map attributes without any issues.
How are you starting LocalStack?
Custom (please describe below)
Steps To Reproduce
How are you starting localstack (e.g., bin/localstack
command, arguments, or doc
91C2
ker-compose.yml
)
I'm using TestContainers in a Node.js environment to start LocalStack. Here's a simplified setup:
import { LocalstackContainer, StartedLocalStackContainer } from '@testcontainers/localstack';
const localStackContainer = await new LocalstackContainer("localstack/localstack:4.1.0")
.withEnvironment({ AWS_DEFAULT_REGION: 'us-east-1', SERVICES: 'sts,events,dynamodb,stepfunctions', DEBUG: '0' })
.start();
const endpoint = localStackContainer.getConnectionUri();
Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)
I'm utilizing the AWS SDK v3 for Node.js to perform the following actions.
- Create a DynamoDB Table:
import { DynamoDBClient, CreateTableCommand } from "@aws-sdk/client-dynamodb";
const dynamoClient = new DynamoDBClient({ endpoint, credentials: { accessKeyId: 'dummy', secretAccessKey: 'dummy' }, region: "us-east-1" });
const createTable = new CreateTableCommand({
TableName: "MyTable",
KeySchema: [
{ AttributeName: "id", KeyType: "HASH" },
],
AttributeDefinitions: [
{ AttributeName: "id", AttributeType: "S" },
],
ProvisionedThroughput: {
ReadCapacityUnits: 5,
WriteCapacityUnits: 5,
},
});
await dynamoClient.send(createTable);
- Insert an Item with a Map Attribute:
import { PutItemCommand } from "@aws-sdk/client-dynamodb";
const putItem = new PutItemCommand({
TableName: "MyTable",
Item: {
id: { S: "1" },
data: { M: { key1: { S: "value1" }, key2: { S: "value2" } } },
},
});
await dynamoClient.send(putItem);
- Create a Step Function:
import { SFNClient, CreateStateMachineCommand } from "@aws-sdk/client-sfn";
const sfnClient = new SFNClient({ endpoint, credentials: { accessKeyId: 'dummy', secretAccessKey: 'dummy' }, region: "us-east-1" });
const stateMachineDefinition = {
Comment: "A simple AWS Step Functions state machine that queries DynamoDB",
StartAt: "QueryDynamoDB",
States: {
QueryDynamoDB: {
Type: "Task",
Resource: "arn:aws:states:::aws-sdk:dynamodb:query",
Parameters: {
TableName: "MyTable",
KeyConditionExpression: "id = :id",
ExpressionAttributeValues: {
":id": { S: "1" },
},
},
End: true,
},
},
};
const createStateMachine = new CreateStateMachineCommand({
name: "MyStateMachine",
definition: JSON.stringify(stateMachineDefinition),
roleArn: "arn:aws:iam::000000000000:role/DummyRole",
});
const stateMachine = await sfnClient.send(createStateMachine);
- Execute the Step Function:
import { StartExecutionCommand } from "@aws-sdk/client-sfn";
const startExecution = new StartExecutionCommand({
stateMachineArn: stateMachine.stateMachineArn,
input: JSON.stringify({ id: "1" }),
});
await sfnClient.send(startExecution);
Environment
- OS: macOS Sequoia 15.3
- LocalStack:
LocalStack version: 4.1.0
LocalStack Docker image sha: sha256:64205c9cc7b885570edfbdb0a97e5ba0802ab5fbeb4efdacf2ddf1206c1cde36
LocalStack build date: 2024/01/30
LocalStack build git hash: 8a211b8ef2c35099bc6813ff24a962d32ddc402e
Anything else?
Logs
2025-01-30 15:55:27
2025-01-30 15:55:27 LocalStack version: 4.1.0
2025-01-30 15:55:27 LocalStack build date: 2025-01-30
2025-01-30 15:55:27 LocalStack build git hash: 8a211b8ef
2025-01-30 15:55:27
2025-01-30 15:55:28 Ready.
2025-01-30 15:55:31 2025-01-30T18:55:31.353 INFO --- [et.reactor-0] localstack.utils.bootstrap : Execution of "require" took 1360.46ms
2025-01-30 15:55:31 2025-01-30T18:55:31.476 INFO --- [et.reactor-0] localstack.request.aws : AWS dynamodb.CreateTable => 200
2025-01-30 15:55:31 2025-01-30T18:55:31.531 INFO --- [et.reactor-1] localstack.request.aws : AWS dynamodb.PutItem => 200
2025-01-30 15:55:34 2025-01-30T18:55:34.829 INFO --- [et.reactor-0] localstack.utils.bootstrap : Execution of "_load_service_plugin" took 3289.18ms
2025-01-30 15:55:34 2025-01-30T18:55:34.829 INFO --- [et.reactor-0] localstack.utils.bootstrap : Execution of "require" took 3289.30ms
2025-01-30 15:55:34 2025-01-30T18:55:34.855 INFO --- [et.reactor-0] localstack.request.aws : AWS stepfunctions.CreateStateMachine => 200
2025-01-30 15:55:34 2025-01-30T18:55:34.924 INFO --- [et.reactor-1] l.services.events.provider : {"InfoCode": "InternalInfoEvents at process_rules", "InfoMessage": "No rules attached to event_bus: default"}
2025-01-30 15:55:34 2025-01-30T18:55:34.927 INFO --- [et.reactor-0] localstack.request.aws : AWS stepfunctions.StartExecution => 200
2025-01-30 15:55:35 2025-01-30T18:55:35.018 ERROR --- [ad-11 (eval)] l.s.s.a.c.eval_component : Exception=FailureEventException, Error=DynamoDB.AmazonDynamoDBException, Details={"taskFailedEventDetails": {"error": "DynamoDB.AmazonDynamoDBException", "cause": "'MapShape' object has no attribute 'members'", "resource": "query", "resourceType": "dynamodb"}} at '(StateTaskServiceDynamoDB| {'state_entered_event_type': <HistoryEventType.TaskStateEntered: 'TaskStateEntered'>, 'state_exited_event_type': <HistoryEventType.TaskStateExited: 'TaskStateExited'>, 'result_path': (ResultPath| {'result_path_src': '$'}, 'result_selector': None, 'retry': None, 'catch': None, 'timeout': (TimeoutSeconds| {'timeout_seconds': 99999999, 'is_default': None}, 'heartbeat': None, 'name': 'QueryDynamoDB', 'query_language': (QueryLanguage| {'query_language_mode': QueryLanguageMode.JSONPath(132)}, 'state_type': <StateType.Task: 16>, 'continue_with': <localstack.services.stepfunctions.asl.component.state.state_continue_with.ContinueWithEnd object at 0xffff1b162d50>, 'comment': None, 'assign_decl': None, 'input_path': (InputPath| {'string_sampler': (StringJsonPath| {'literal_value': '$', 'json_path': '$'}}, 'output_path': (OutputPath| {'string_sampler': (StringJsonPath| {'literal_value': '$', 'json_path': '$'}}, 'output': None, 'resource': (ServiceResource| {'_region': '', '_account': '', 'resource_arn': 'arn:aws:states:::dynamodb:query', 'partition': 'aws', 'service_name': 'dynamodb', 'api_name': 'dynamodb', 'api_action': 'query', 'condition': None}, 'parargs': (Parameters| {'template_eval_component': (PayloadTmpl| {'payload_bindings': [(PayloadBindingValue| {'field': 'TableName', 'payload_value': (PayloadValueStr| {'val': 'MyTable'}}, (PayloadBindingValue| {'field': 'KeyConditionExpression', 'payload_value': (PayloadValueStr| {'val': 'id = :id'}}, (PayloadBindingValue| {'field': 'ExpressionAttributeValues', 'payload_value': (PayloadTmpl| {'payload_bindings': [(PayloadBindingValue| {'field': ':id', 'payload_value': (PayloadTmpl| {'payload_bindings': [(PayloadBindingValue| {'field': 'S', 'payload_value': (PayloadValueStr| {'val': '1'}}]}}]}}]}}, 'credentials': None}'
2025-01-30 15:55:35 2025-01-30T18:55:35.020 INFO --- [et.reactor-0] l.services.events.provider : {"InfoCode": "InternalInfoEvents at process_rules", "InfoMessage": "No rules attached to event_bus: default"}