microsoft/semantic-kernel · error · NotImplementedError

Unsupported operator: {type(op)}

Error message

Unsupported operator: {type(op)}

What it means

A NotImplementedError raised by _lambda_parser when a filter lambda uses a binary comparison operator that has no Chroma mapping. The code maps ast.Eq, NotEq, Gt, GtE, Lt, LtE (and BoolOp And/Or); any other Compare operator — most notably ast.In / ast.Is / ast.IsNot — falls through to 'raise NotImplementedError(f"Unsupported operator: {type(op)}")'. This is part of translating a Python lambda into Chroma's where-filter dict.

Source

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

                match op:
                    case ast.In():
                        return {left: {"$in": right}}  # type: ignore
                    case ast.NotIn():
                        return {left: {"$nin": right}}  # type: ignore
                    case ast.Eq():
                        # Chroma allows short form: {field: value}
                        return {left: right}  # type: ignore
                    case ast.NotEq():
                        return {left: {"$ne": right}}  # type: ignore
                    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():

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Rewrite the filter using only the supported comparisons (==, !=, >, >=, <, <=) combined with 'and'/'or'.
  2. For membership, expand manually: lambda x: (x.tag == "a") or (x.tag == "b").
  3. For null checks use == None / != None (Eq/NotEq) rather than 'is'.

Example fix

// before
lambda x: x.tag in ["a", "b"]
// after
lambda x: (x.tag == "a") or (x.tag == "b")
Defensive patterns

Strategy: validation

Validate before calling

import ast
ALLOWED = {ast.Eq, ast.NotEq, ast.Gt, ast.GtE, ast.Lt, ast.LtE}
ops = [n.ops[0] for n in ast.walk(ast.parse(filter_lambda_src, mode="eval")) if isinstance(n, ast.Compare)]
assert all(type(o) in ALLOWED for o in ops), "Filter uses an unsupported comparison operator"

Type guard

import ast
ALLOWED_CMP = {ast.Eq, ast.NotEq, ast.Gt, ast.GtE, ast.Lt, ast.LtE}

def filter_uses_only_supported_ops(src: str) -> bool:
    tree = ast.parse(src, mode="eval")
    return all(type(o) in ALLOWED_CMP
               for n in ast.walk(tree) if isinstance(n, ast.Compare)
               for o in n.ops)

Try / catch

try:
    results = await collection.vectorized_search(vector=v, options=VectorSearchOptions(filter=lambda x: x.t in ["a","b"]))
except NotImplementedError as e:
    if "Unsupported operator" in str(e):
        # rewrite filter without 'in'/'is'
        ...

Prevention

When it happens

Trigger: Writing a collection filter lambda that uses 'in' (membership), 'is', or 'is not' between a field and a value, e.g. lambda x: x.tag in ["a","b"] or lambda x: x.val is None.

Common situations: Translating SQL/Pandas-style filters that lean on 'in'; treating Chroma like a document DB with $in support without checking the supported AST node set.

Related errors


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