microsoft/semantic-kernel · error · NotImplementedError

Unary +, -, ~ and ! are not supported in Chroma filters.

Error message

Unary +, -, ~ and ! are not supported in Chroma filters.

What it means

A NotImplementedError raised by _lambda_parser for any ast.UnaryOp node. Chroma filters do not support unary plus, minus, bitwise-not, or logical-not applied in the lambda, so unary operators are rejected outright (e.g. lambda x: -x.value or lambda x: not x.active are unsupported). Note: logical 'not' in Python is a UnaryOp (ast.Not), so it is caught here too.

Source

Thrown at python/semantic_kernel/connectors/chroma.py:409

                    case ast.Gt():
                        return {left: {"$gt": right}}  # type: ignore
                    case ast.GtE():
                        return {left: {"$gte": right}}  # type: ignore
                    case ast.Lt():
                        return {left: {"$lt": right}}  # type: ignore
                    case ast.LtE():
                        return {left: {"$lte": right}}  # type: ignore
                raise NotImplementedError(f"Unsupported operator: {type(op)}")
            case ast.BoolOp():
                op = node.op  # type: ignore
                values = [self._lambda_parser(v) for v in node.values]
                if isinstance(op, ast.And):
                    return {"$and": values}
                if isinstance(op, ast.Or):
                    return {"$or": values}
                raise NotImplementedError(f"Unsupported BoolOp: {type(op)}")
            case ast.UnaryOp():
                raise NotImplementedError("Unary +, -, ~ and ! are not supported in Chroma filters.")
            case ast.Attribute():
                # Only allow attributes that are in the data model
                if node.attr not in self.definition.storage_names:
                    raise VectorStoreOperationException(
                        f"Field '{node.attr}' not in data model (storage property names are used)."
                    )
                return node.attr
            case ast.Name():
                # Only allow names that are in the data model
                if node.id not in self.definition.storage_names:
                    raise VectorStoreOperationException(
                        f"Field '{node.id}' not in data model (storage property names are used)."
                    )
                return node.id
            case ast.Constant():
                value = node.value
                if isinstance(value, str):
                    return value.replace("'", "''")

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Replace 'not x.flag' with an explicit inequality: lambda x: x.flag == False.
  2. Rewrite any sign-flip logic so the comparison value is pre-computed outside the lambda (e.g. compare against -threshold directly).
  3. Restructure boolean logic to use only 'and'/'or' plus the six supported comparison operators.

Example fix

// before
lambda x: not x.active
// after
lambda x: x.active == False
Defensive patterns

Strategy: validation

Validate before calling

import ast
tree = ast.parse(filter_lambda_src, mode="eval")
assert not any(isinstance(n, ast.UnaryOp) for n in ast.walk(tree)), (
    "Filter lambdas must not use unary -, +, ~, or not"
)

Type guard

import ast

def filter_has_no_unaryops(src: str) -> bool:
    tree = ast.parse(src, mode="eval")
    return not any(isinstance(n, ast.UnaryOp) for n in ast.walk(tree))

Try / catch

try:
    results = await collection.vectorized_search(vector=v, options=opts)
except NotImplementedError as e:
    if "Unary" in str(e):
        # rewrite 'not x.flag' as 'x.flag == False'
        ...

Prevention

When it happens

Trigger: Writing a filter lambda with a leading '-', '+', '~', or 'not', including 'not x.flag' which compiles to ast.UnaryOp(ast.Not, ...).

Common situations: Attempting negation of a boolean flag ('not x.active') or numeric sign flip inside a filter; porting boolean logic that relies on 'not'.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/1b9ac97393c1d8c8. Report an issue: GitHub.