boto/boto3 · error · DynamoDBOperationNotSupportedError

AND operation cannot be applied to value

Error message

AND 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

DynamoDB condition expressions are built from ConditionBase objects (And, Or, Not, Equals, etc.). When you use the & operator on a ConditionBase instance with something that is not itself a ConditionBase, boto3 raises DynamoDBOperationNotSupportedError('AND', other). The library cannot fold a raw Python value into a condition expression because there is no defined mapping from arbitrary types to a DynamoDB condition.

Solutions

  1. Ensure both operands of & are ConditionBase instances produced by Attr()/Key() comparison methods (eq, lt, gt, begins_with, etc.).
  2. Guard dynamic condition building: only apply & when the candidate is an instance of ConditionBase, otherwise wrap it with Attr(name).eq(value).
  3. If a variable may be None, default it to a neutral condition or skip the & operation entirely.

Example fix

# before
cond = Attr('status').eq('ACTIVE') & maybe_filter  # maybe_filter may be None
# after
cond = Attr('status').eq('ACTIVE')
if maybe_filter is not None:
    cond = cond & maybe_filter
Defensive patterns

Strategy: type-guard

Validate before calling

from boto3.dynamodb.conditions import ConditionBase
assert isinstance(left, ConditionBase) and isinstance(right, ConditionBase), \
    'Both operands of & must be ConditionBase instances'

Type guard

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

Try / catch

from boto3.exceptions import DynamoDBOperationNotSupportedError
try:
    expr = base & extra
except DynamoDBOperationNotSupportedError:
    extra = Attr('fallback').eq(True)
    expr = base & extra

Prevention

When it happens

Trigger: Writing Key('pk').eq('x') & 'some_string', Attr('n').lt(5) & True, or chaining & with a previously-rendered string/expression. Also occurs when an operand is None because a condition variable was never assigned.

Common situations: Building filter_expression or key_condition_expression dynamically where one branch accidentally yields None or a scalar; refactoring a query and leaving a placeholder value; confusing the logical-and of two conditions (both ConditionBase) with comparing an attribute to a value.

Related errors


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

Appendix: source

Thrown at boto3/dynamodb/conditions.py:35

    DynamoDBNeedsConditionError,
    DynamoDBNeedsKeyConditionError,
    DynamoDBOperationNotSupportedError,
)

ATTR_NAME_REGEX = re.compile(r'[^.\[\]]+(?![^\[]*\])')


class ConditionBase:
    expression_format = ''
    expression_operator = ''
    has_grouped_values = False

    def __init__(self, *values):
        self._values = values

    def __and__(self, other):
        if not isinstance(other, ConditionBase):
            raise DynamoDBOperationNotSupportedError('AND', other)
        return And(self, other)

    def __or__(self, other):
        if not isinstance(other, ConditionBase):
            raise DynamoDBOperationNotSupportedError('OR', other)
        return Or(self, other)

    def __invert__(self):
        return Not(self)

    def get_expression(self):
        return {
            'format': self.expression_format,
            'operator': self.expression_operator,
            'values': self._values,
        }

    def __eq__(self, other):

View on GitHub (pinned to 6e10b029c1)