I'm getting a 500 Internal Error when trying to perform an update using an UpdateExpression using the Node.js AWS SDK (AWS.DynamoDB.DocumentClient).
The operation hangs for about 30 seconds and then returns this error:
InternalFailure: null
at Request.extractError (WORKSPACE/node_modules/aws-sdk/lib/protocol/json.js:52:27)
at Request.callListeners (WORKSPACE/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (WORKSPACE/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (WORKSPACE/node_modules/aws-sdk/lib/request.js:688:14)
at Request.transition (WORKSPACE/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (WORKSPACE/node_modules/aws-sdk/lib/state_machine.js:14:12)
at WORKSPACE/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (WORKSPACE/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (WORKSPACE/node_modules/aws-sdk/lib/request.js:690:12)
at Request.callListeners (WORKSPACE/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
code: 'InternalFailure',
time: 2021-10-08T16:24:49.756Z,
requestId: 'EJJH7IIRFCS0HOPNQ9IIS39CKJVV4KQNSO5AEMVJF66Q9ASUAAJG',
statusCode: 500,
retryable: true
}
I get this both when running my code in a Lambda function as well as when running locally using the DynamoDB REST API (so it's not a Lambda permission issue).
What's causing this internal error?
My code to update the item:
export async function addOverride(addOverrideRequest: any) {
const addListIfNotExists = {
TableName: addOverrideRequest.table,
Key: {
Environment: addOverrideRequest.environment
},
UpdateExpression: "SET Overrides.:overrideAttr = :emptylist",
ConditionExpression: "attribute_not_exists(Overrides.:overrideAttr)",
ExpressionAttributeValues: {
":overrideAttr": addOverrideRequest.overrideField,
":emptylist": [],
},
}
try {
const result = await DOCUMENT_CLIENT.update(addListIfNotExists).promise();
} catch (error) {
throw error;
}
}
The request resolves as:
{
TableName: 'AppVersions',
Key: { Environment: 'int' },
UpdateExpression: 'SET Overrides.:overrideAttr = :emptylist',
ConditionExpression: 'attribute_not_exists(Overrides.:overrideAttr)',
ExpressionAttributeValues: { ':overrideAttr': 'EyeTrackerType', ':emptylist': [] }
}
CodePudding user response:
While you can update attributes of a nested map, you can't define the attribute name itself dynamically in your request.
This means that your UpdateExpression, ConditionExpression & ExpressionAttributeValues need to have the attribute name hardcoded, which is EyeTrackerType in this case.
This should work:
const addListIfNotExists = {
TableName: addOverrideRequest.table,
Key: {
Environment: addOverrideRequest.environment
},
UpdateExpression: "SET Overrides.EyeTrackerType = :emptylist",
ConditionExpression: "attribute_not_exists(Overrides.EyeTrackerType)",
ExpressionAttributeValues: {
":emptylist": []
}
}
To keep it dynamic, I would create the UpdateExpression & ConditionExpression based on your business logic before passing it to AWS.
