microsoft/semantic-kernel · error · NotImplementedError
Left side must be x.FIELD.
Error message
Left side must be x.FIELD.
What it means
SearchLambdaVisitor (used by Brave/Google search filter lambdas) only accepts comparisons of the exact shape `x.FIELD == VALUE`. The left operand must be an ast.Attribute access on an ast.Name (the lambda parameter). Anything else on the left raises NotImplementedError.
Source
Thrown at python/semantic_kernel/connectors/_search_shared.py:30
class SearchLambdaVisitor(ast.NodeVisitor):
"""Visitor to parse a lambda function for Brave and Google Search filters."""
def __init__(self, valid_parameters: list[str]):
"""Initialize the visitor with a list of valid parameters."""
self.filters: list[dict[str, str]] = []
self.valid_parameters = valid_parameters
@override
def visit_Lambda(self, node):
self.visit(node.body)
@override
def visit_Compare(self, node):
# Only support x.FIELD == VALUE
if not (isinstance(node.left, ast.Attribute) and isinstance(node.left.value, ast.Name)):
raise NotImplementedError("Left side must be x.FIELD.")
field = node.left.attr
if not (len(node.ops) == 1 and isinstance(node.ops[0], ast.Eq)):
raise NotImplementedError("Only == comparisons are supported.")
right = node.comparators[0]
if isinstance(right, ast.Constant):
if right.value is None:
raise NotImplementedError("None values are not supported.")
value = str(right.value)
else:
raise NotImplementedError("Only constant values are supported on the right side.")
if field not in self.valid_parameters:
raise ValueError(f"Field '{field}' is not supported.")
self.filters.append({field: quote_plus(value)})
@override
def visit_BoolOp(self, node):
if not isinstance(node.op, ast.And):
raise NotImplementedError("Only 'and' of == comparisons is supported.")View on GitHub (pinned to c028a0c7dc)
Solutions
- Rewrite the filter so the left side is the parameter attribute: `lambda x: x.field == VALUE`.
- Move any transformation into the constant value, not the field side.
Example fix
// before lambda x: "news" == x.category # value on the left lambda x: str(x.year) == "2024" # call on the left // after lambda x: x.category == "news" lambda x: x.year == 2024
Defensive patterns
Strategy: validation
Validate before calling
import ast
node = ast.parse(filter_src, mode='eval').body # the lambda
def check_left(n):
if isinstance(n, ast.Compare):
assert isinstance(n.left, ast.Attribute) and isinstance(n.left.value, ast.Name), 'left must be x.FIELD'
if isinstance(n, ast.BoolOp):
for v in n.values: check_left(v)
check_left(node.body) Type guard
def is_x_field_compare(node: ast.Compare) -> bool:
return isinstance(node.left, ast.Attribute) and isinstance(node.left.value, ast.Name) Prevention
- Write filter lambdas as `lambda x: x.FIELD == VALUE` only
- Keep the field on the left, value on the right
- Validate filter syntax against the documented DSL before runtime
When it happens
Trigger: Supplying a filter lambda whose left side is not `x.FIELD`: a reversed comparison (`lambda x: VALUE == x.field`), a call expression (`func(x.field) == ...`), a subscript, or a bare comparison without an attribute.
Common situations: Writing the value first; wrapping the field in a function; using a comparison the visitor does not model.
Related errors
- Only == comparisons are supported.
- None values are not supported.
- Only constant values are supported on the right side.
- Only 'and' of == comparisons is supported.
- Field '{field}' is not supported.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/df51ec19414f386d.
Report an issue: GitHub.