Home > Net >  AWS: DynamoDB item update with update expression causes 500 InternalFailure & 30 second hang
AWS: DynamoDB item update with update expression causes 500 InternalFailure & 30 second hang

Time:10-12

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.

  • Related