boto/boto3 · error · DynamoDBOperationNotSupportedError

NOT operation cannot be applied to value

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

AttributeBase.__invert__ raises DynamoDBOperationNotSupportedError('NOT', self) so that ~Attr('x') does not silently produce a bitwise complement. NOT is only defined on a ConditionBase; inverting a bare attribute is meaningless because there is no condition to negate.

Solutions

  1. Apply ~ to a ConditionBase: ~Attr('flag').eq(True).
  2. For 'attribute does not exist', use ~Attr('flag').exists() or Attr('flag').not_exists().
  3. Ensure the operand of ~ is the return value of an Attr()/Key() comparison method.

Example fix

# before
expr = ~Attr('deleted')
# after
expr = ~Attr('deleted').eq(True)
# or
expr = Attr('deleted').not_exists()
Defensive patterns

Strategy: validation

Validate before calling

from boto3.dynamodb.conditions import ConditionBase
def safe_not(c):
    assert isinstance(c, ConditionBase), 'Apply ~ to a ConditionBase, not a bare attribute'
    return ~c

Type guard

from boto3.dynamodb.conditions import ConditionBase
def is_negatable(v) -> bool:
    return isinstance(v, ConditionBase)

Try / catch

from boto3.exceptions import DynamoDBOperationNotSupportedError
try:
    expr = ~attr
except DynamoDBOperationNotSupportedError:
    expr = ~attr.eq(True)

Prevention

When it happens

Trigger: ~Attr('flag'), ~Key('pk'), or any unary ~ applied to a raw AttributeBase instead of to a ConditionBase.

Common situations: Expecting ~ to mean 'attribute does not exist' or 'attribute is absent'; refactoring and stripping a comparison method while leaving the ~ operator.

Related errors


AI-assisted analysis of boto/boto3@6e10b029c1 (2026-08-11). Data as JSON: /api/errors/b224280c78a2f066. Report an issue: GitHub.

Appendix: 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 6e10b029c1)