boto/boto3 · error · DynamoDBNeedsConditionError

Expecting a ConditionBase object. Got {value} of type {type(

Error message

Expecting a ConditionBase object. Got {value} of type {type(value)}. Use AttributeBase object methods (i.e. Attr().eq()). to generate ConditionBase instances.

What it means

Raised by ConditionExpressionBuilder.build_expression() when the object passed as a condition is not a ConditionBase. The builder recurses through the condition tree emitting placeholders; a non-condition (raw value, bare Attr/Key, or unrelated object) cannot be processed. This is typically surfaced when a table.query / table.scan / item.update receives a FilterExpression, ConditionExpression, or KeyConditionExpression that is not a fully-built condition.

Source

Thrown at boto3/dynamodb/conditions.py:344

        :type condition: ConditionBase
        :param condition: A condition to be built into a condition expression
            string with any necessary placeholders.

        :type is_key_condition: Boolean
        :param is_key_condition: True if the expression is for a
            KeyConditionExpression. False otherwise.

        :rtype: (string, dict, dict)
        :returns: Will return a string representing the condition with
            placeholders inserted where necessary, a dictionary of
            placeholders for attribute names, and a dictionary of
            placeholders for attribute values. Here is a sample return value:

            ('#n0 = :v0', {'#n0': 'myattribute'}, {':v1': 'myvalue'})
        """
        if not isinstance(condition, ConditionBase):
            raise DynamoDBNeedsConditionError(condition)
        attribute_name_placeholders = {}
        attribute_value_placeholders = {}
        condition_expression = self._build_expression(
            condition,
            attribute_name_placeholders,
            attribute_value_placeholders,
            is_key_condition=is_key_condition,
        )
        return BuiltConditionExpression(
            condition_expression=condition_expression,
            attribute_name_placeholders=attribute_name_placeholders,
            attribute_value_placeholders=attribute_value_placeholders,
        )

    def _build_expression(
        self,
        condition,
        attribute_name_placeholders,

View on GitHub (pinned to c7b4afac23)

Solutions

  1. Ensure the expression is a ConditionBase: table.query(KeyConditionExpression=Key('pk').eq('v')).
  2. For filter expressions, call a comparison/method on Attr: Attr('x').eq(1) or Attr('x').exists().
  3. If you must build from strings, use raw KeyConditionExpression strings with explicit placeholders instead of the builder.

Example fix

# before
table.query(KeyConditionExpression=Key('pk'))

# after
table.query(KeyConditionExpression=Key('pk').eq('user#1'))
Defensive patterns

Strategy: type-guard

Validate before calling

from boto3.dynamodb.conditions import ConditionBase

def check_expression(expr):
    if not isinstance(expr, ConditionBase):
        raise TypeError(f'Expected ConditionBase, got {type(expr).__name__}')
    return expr

Type guard

from boto3.dynamodb.conditions import ConditionBase

def is_condition(v) -> bool:
    return isinstance(v, ConditionBase)

Try / catch

from boto3.exceptions import DynamoDBNeedsConditionError
try:
    table.scan(FilterExpression=expr)
except DynamoDBNeedsConditionError:
    # expr was not a built condition; rebuild it
    table.scan(FilterExpression=Attr('x').eq(expr))

Prevention

When it happens

Trigger: table.query(KeyConditionExpression=Key('pk')) — missing .eq()/.begins_with(); table.scan(FilterExpression=Attr('x')) — bare Attr; passing a plain dict or string to FilterExpression.

Common situations: Forgetting the terminal comparison method on Key/Attr; passing a raw attribute name string instead of a condition object; refactoring that drops the final method call.

Related errors


AI-assisted analysis of boto/boto3@c7b4afac23 (2026-08-04). Data as JSON: /data/errors/99c4ca6cb38bbd48.json. Report an issue: GitHub.