Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: value

Question:

I am trying to update the record in dynamodb using following dictData, I have RESERVER_KEYWORDS array which has reserved keyword in dynamoDB. Please check code segment which I am trying to replace with the reserve keyword. Main issue that customer.value and action.value type of keyword used in given record. I am not sure how to replace with #.

However I am getting error

CRITICAL Couldn’t update record in table table. Here’s why: ValidationException: Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: value

  dictData = {
    ':line_items': [{
        'search_product': 'dd',
        'quantity': '10'
    }]
    'email': 'xyz@email',
    'poc_name': 'XYZ',
    'contact': '90912',
    'action': {
        'value': 'id1',
        'label': 'In Progress'
    },
    'terms': 'Cash',
    'customer': {
        'value': 'id1',
        'label': 'Customer'
    },
   }

In side the function definition:

updateExpression = ["set "]
updateValues = dict()
expression_attributes_names = {}
for key, value in dictData.items():
    updateExpression.append(f" #{key}_alias = :{key.replace('.', '_')},")
    updateValues[f":{key.replace('.', '_')}"] = value
    expression_attributes_names[f"#{key}_alias"] = key
    response = table.update_item(
       Key={"_id": id},
       UpdateExpression="".join(updateExpression)[:-1],
       ExpressionAttributeValues=updateValues,
       ReturnValues="UPDATED_NEW",
       ExpressionAttributeNames=expression_attributes_names,
    )
       

Above function will give following values of expression_attributes_names, updateExpression, updateValues.

 expression_attributes_names: {}    

 updateExpression: ['set ', ' line_items = :line_items,', ' email = :email', ' poc_name = :poc_name,', ' contact = :contact,', ' action.value = :action_value,',
    ' action.label = :action_label,', ' terms = :terms,',
    ' customer.value = :customer_value,', ' customer.label = :customer_label,'
]

 updateValues: {
    ':line_items': [{
        'search_product': 'dd',
        'quantity': '10'
    }],
    ':email': 'xyz@email',
    ':poc_name': 'Test',
    ':contact': '90912',
    ':action_value': 'id1',
    ':action_label': 'In Progress',
    ':terms': 'Cash',
    ':customer_value': 'id1',
    ':customer_label': 'Customer'
 }
Asked By: Neelabh Singh

||

Answers:

You should always use ExpressionAttributeNames to ensure you do not conflict with DynamoDB reserved keywords.

https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html#DDB-UpdateItem-request-ExpressionAttributeNames

Furthermore, I believe you should look into the parameters expected of UpdateItem to ensure you are passing correct values:

https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html

For nested values you just follow the same concept:

#customer.#value

ExpressionAttributeNames={ 
   "#customer":"customer",
   "#value":"value"
   },
UpdateExpression="SET #customer.#value = :val"

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html#Expressions.ExpressionAttributeNames.NestedAttributes

Answered By: Lee Hannigan