Home > Blockchain >  Why does a DynamoDB item update with an update expression cause a 500 InternalFailure & a 30 second
Why does a DynamoDB item update with an update expression cause a 500 InternalFailure & a 30 second

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:

Use ExpressionAttributeNames to define your attribute names, instead of adding them to ExpressionAttributeValues.


ExpressionAttributeNames are used to specify dynamic attribute names, however, you're specifying overrideAttr inside ExpressionAttributeValues.

Also, you must use the hash sign - # - for indicating placeholders for attribute names.

This should work:

const addListIfNotExists = {
    TableName: addOverrideRequest.table,
    Key: {
        Environment: addOverrideRequest.environment
    },
    UpdateExpression: "SET Overrides.#overrideAttr = :emptylist",
    ConditionExpression: "attribute_not_exists(Overrides.#overrideAttr)",
    ExpressionAttributeNames: {
        "#overrideAttr": addOverrideRequest.overrideField
    },
    ExpressionAttributeValues: {
        ":emptylist": []
    },
}
  • Related