boto/boto3 · error · DynamoDBOperationNotSupportedError
NOT operation cannot be applied to value {value} of type {ty
Error message
NOT operation cannot be applied to value {value} of type {type(value)} directly. Must use AttributeBase object methods (i.e. Attr().eq()). to generate ConditionBase instances first. What it means
Raised by AttributeBase.__invert__ (~) when the unary NOT operator is applied to a bare Attr/Key that has not been turned into a ConditionBase. You cannot negate a raw attribute; you must first build a condition (e.g. Attr('x').eq(1)) and then negate that condition with ~.
Source
Thrown at boto3/dynamodb/conditions.py:74
return True
return False
def __ne__(self, other):
return not self.__eq__(other)
class AttributeBase:
def __init__(self, name):
self.name = name
def __and__(self, value):
raise DynamoDBOperationNotSupportedError('AND', self)
def __or__(self, value):
raise DynamoDBOperationNotSupportedError('OR', self)
def __invert__(self):
raise DynamoDBOperationNotSupportedError('NOT', self)
def eq(self, value):
"""Creates a condition where the attribute is equal to the value.
:param value: The value that the attribute is equal to.
"""
return Equals(self, value)
def lt(self, value):
"""Creates a condition where the attribute is less than the value.
:param value: The value that the attribute is less than.
"""
return LessThan(self, value)
def lte(self, value):
"""Creates a condition where the attribute is less than or equal to the
value.View on GitHub (pinned to c7b4afac23)
Solutions
- Call a comparison method before ~: ~(Attr('x').eq(1)).
- For 'attribute does not exist' use Attr('x').not_exists() directly (no ~ needed).
- Remember that ~ negates a ConditionBase, not an AttributeBase.
Example fix
# before
fe = ~Attr('x')
# after (negate a condition)
fe = ~Attr('x').eq(1)
# or, if intent was 'attribute does not exist'
fe = Attr('x').not_exists() Defensive patterns
Strategy: type-guard
Validate before calling
from boto3.dynamodb.conditions import ConditionBase, AttributeBase
def safe_not(item):
if isinstance(item, AttributeBase) and not isinstance(item, ConditionBase):
raise TypeError(f'Cannot apply ~ to bare Attr/Key {item.name!r}; call a comparison method first')
return ~item Type guard
from boto3.dynamodb.conditions import ConditionBase
def is_built_condition(v) -> bool:
return isinstance(v, ConditionBase) Try / catch
from boto3.exceptions import DynamoDBOperationNotSupportedError
try:
fe = ~attr_x
except DynamoDBOperationNotSupportedError:
fe = ~attr_x.eq(1) Prevention
- Use Attr('x').not_exists() / .exists() for existence checks instead of ~Attr.
- Never place ~ directly before Attr()/Key() — always before a complete condition.
When it happens
Trigger: table.scan(FilterExpression=~Attr('x')) — no comparison method called. Also ~Key('pk') or ~Attr('x').
Common situations: Trying to express 'NOT x' (attribute does not exist) but using ~Attr instead of Attr('x').not_exists(); translating logical NOT naively.
Related errors
- AND operation cannot be applied to value {value} of type {ty
- OR operation cannot be applied to value {value} of type {typ
- Expecting a ConditionBase object. Got {value} of type {type(
- Attribute object {value.name} is of type {type(value)}. KeyC
- Value must be of the following types: {types}
AI-assisted analysis of boto/boto3@c7b4afac23 (2026-08-04).
Data as JSON: /data/errors/b224280c78a2f066.json.
Report an issue: GitHub.