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
- Ensure both operands of & are ConditionBase instances produced by Attr()/Key() comparison methods (eq, lt, gt, begins_with, etc.).
- Guard dynamic condition building: only apply & when the candidate is an instance of ConditionBase, otherwise wrap it with Attr(name).eq(value).
- 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
- Never & raw values; always Attr()/Key().method().
- When building dynamic conditions, type-check operands before combining.
- Default optional conditions to None and branch instead of &-ing them.
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
- Expecting a ConditionBase object. Got
- OR operation cannot be applied to value
- Attribute object is of type . KeyConditionExpression only…
- NOT operation cannot be applied to value
- Dynamodb type is not supported
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)