boto/boto3 · error · DynamoDBOperationNotSupportedError

OR operation cannot be applied to value

Error message

OR 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

Symmetric to the AND case: the | operator is defined on ConditionBase and only accepts another ConditionBase. Applying | with a non-ConditionBase raises DynamoDBOperationNotSupportedError('OR', other), because DynamoDB OR semantics only exist between condition expressions, not between an expression and a raw value.

Solutions

  1. Use Attr(name).is_in([...]) for value-set membership instead of OR-ing scalar literals.
  2. Verify every operand of | is a ConditionBase before applying it.
  3. Filter out None/empty operands when constructing OR chains dynamically.

Example fix

# before
expr = Attr('role').eq('admin') | 'user' | 'guest'
# after
expr = Attr('role').is_in(['admin', 'user', 'guest'])
Defensive patterns

Strategy: type-guard

Validate before calling

from boto3.dynamodb.conditions import ConditionBase
operands = [a, b, c]
assert all(isinstance(o, ConditionBase) for o in operands), \
    'OR operands must be ConditionBase; use Attr(name).is_in([...]) for value sets'

Type guard

from boto3.dynamodb.conditions import ConditionBase
def all_conditions(values):
    return all(isinstance(v, ConditionBase) for v in values)

Try / catch

from boto3.exceptions import DynamoDBOperationNotSupportedError
try:
    expr = base | extra
except DynamoDBOperationNotSupportedError:
    # fallback to a membership check
    expr = Attr('role').is_in(['a', 'b'])

Prevention

When it happens

Trigger: Key('pk').eq('a') | 'b', Attr('flag').eq(1) | [1,2,3], or any | where one side is a literal/None/str instead of a ConditionBase.

Common situations: Trying to express 'attribute equals any of these values' with | instead of Attr(...).is_in([...]); building OR chains from user input where one input is missing.

Related errors


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

Appendix: source

Thrown at boto3/dynamodb/conditions.py:40

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):
        if isinstance(other, type(self)):
            if self._values == other._values:
                return True
        return False

View on GitHub (pinned to 6e10b029c1)