'Does Boto3 DynamoDB have reserved attribute names for update_item with conditions expressions? Unexpected attribute SET behavior

I've implemented a simple object versioning scheme that allows the calling code to supply a current_version integer that that will set the ConditionExpression. I've also implemented a simple timestamping scheme to set an attribute named auto_timestamp to the current unix timestamp.

When the ConditionExpression is supplied with the object's current version integer, the update occurs, but also sets auto_timestamp to the current version value, rather than the value supplied in ExpressionAttributeValues. This only occurs if the attribute names are #a0, #a1 ... and values are :v0, :v1 ...

For example, this runs as expected without the condition, and auto_timestamp is set to 1643476414 in the table. The if_not_exists is used to start the object version at 0 if the item does not yet exist or did not previously have a auto_object_version attribute.

update_kwargs = {
    "Key": {"user_id": user_id},
    "UpdateExpression": 'SET #a0 = :v0, #a1 = if_not_exists(#a1, :zero) + :v1',
    "ExpressionAttributeNames": {"#a0": "auto_timestamp", "#a1": "auto_object_version"},
    "ExpressionAttributeValues": {":v0": 1643476414, ":v1": 1, ":zero": 0}
}
table.update_item(**update_kwargs)

However, this example runs without exception, but auto_timestamp is set to 1. This behavior continues for each subsequent increment of current_version for additional calls to update_item

from boto3.dynamodb.conditions import Attr
update_kwargs = {
    "Key": {"user_id": user_id},
    "UpdateExpression": 'SET #a0 = :v0, #a1 = if_not_exists(#a1, :zero) + :v1',
    "ExpressionAttributeNames": {"#a0": "auto_timestamp", "#a1": "auto_object_version"},
    "ExpressionAttributeValues": {":v0": 1643476414, ":v1": 1, ":zero": 0}
    "ConditionExpression": Attr("auto_object_version").eq(1)
}
table.update_item(**update_kwargs)

While debugging, I changed the scheme by which I am labeling the attribute names and values to use #att instead of #a and :val instead of :v and the following works as desired and auto_timestamp is set to 1643476414:

from boto3.dynamodb.conditions import Attr
update_kwargs = {
    "Key": {"user_id": user_id},
    "UpdateExpression": 'SET #att0 = :val0, #att1 = if_not_exists(#att1, :zero) + :val1',
    "ExpressionAttributeNames": {"#att0": "auto_timestamp", "#att1": "auto_object_version"},
    "ExpressionAttributeValues": {":val0": 1643476414, ":val1": 1, ":zero": 0}
    "ConditionExpression": Attr("auto_object_version").eq(1)
}
table.update_item(**update_kwargs)

I couldn't find any documentation on reserved attribute names or values that shouldn't be used for keys in ExpressionAttributeNames or ExpressionAttributeValues.

Is this behavior anyone has witnessed before? The behavior is easily worked around when switching the string formatting used to generate the keys but was very unexpected.



Solution 1:[1]

There are no reserved attribute or value names, and I routinely use names like :v1 and #a1 in my own tests, and they seem to work fine.

Assuming you correctly copied-pasted your code into the question, it seems to me you simply have a syntax error in your code - you are missing a double-quote after the "auto_timestamp. What I don't understand, though, is how this compiles or why changing a to att changed anything. Please be more careful in pasting a self-contained code snippet that works or doesn't work.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nadav Har'El