{"record":{"id":"1b9ac97393c1d8c8","repo":"microsoft/semantic-kernel","slug":"unary-and-are-not-supported-in-chroma-fi","errorCode":null,"errorMessage":"Unary +, -, ~ and ! are not supported in Chroma filters.","messagePattern":"Unary \\+, -, ~ and ! are not supported in Chroma filters\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/chroma.py","lineNumber":409,"sourceCode":"                    case ast.Gt():\n                        return {left: {\"$gt\": right}}  # type: ignore\n                    case ast.GtE():\n                        return {left: {\"$gte\": right}}  # type: ignore\n                    case ast.Lt():\n                        return {left: {\"$lt\": right}}  # type: ignore\n                    case ast.LtE():\n                        return {left: {\"$lte\": right}}  # type: ignore\n                raise NotImplementedError(f\"Unsupported operator: {type(op)}\")\n            case ast.BoolOp():\n                op = node.op  # type: ignore\n                values = [self._lambda_parser(v) for v in node.values]\n                if isinstance(op, ast.And):\n                    return {\"$and\": values}\n                if isinstance(op, ast.Or):\n                    return {\"$or\": values}\n                raise NotImplementedError(f\"Unsupported BoolOp: {type(op)}\")\n            case ast.UnaryOp():\n                raise NotImplementedError(\"Unary +, -, ~ and ! are not supported in Chroma filters.\")\n            case ast.Attribute():\n                # Only allow attributes that are in the data model\n                if node.attr not in self.definition.storage_names:\n                    raise VectorStoreOperationException(\n                        f\"Field '{node.attr}' not in data model (storage property names are used).\"\n                    )\n                return node.attr\n            case ast.Name():\n                # Only allow names that are in the data model\n                if node.id not in self.definition.storage_names:\n                    raise VectorStoreOperationException(\n                        f\"Field '{node.id}' not in data model (storage property names are used).\"\n                    )\n                return node.id\n            case ast.Constant():\n                value = node.value\n                if isinstance(value, str):\n                    return value.replace(\"'\", \"''\")","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/chroma.py#L391-L427","documentation":"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.","triggerScenarios":"Writing a filter lambda with a leading '-', '+', '~', or 'not', including 'not x.flag' which compiles to ast.UnaryOp(ast.Not, ...).","commonSituations":"Attempting negation of a boolean flag ('not x.active') or numeric sign flip inside a filter; porting boolean logic that relies on 'not'.","solutions":["Replace 'not x.flag' with an explicit inequality: lambda x: x.flag == False.","Rewrite any sign-flip logic so the comparison value is pre-computed outside the lambda (e.g. compare against -threshold directly).","Restructure boolean logic to use only 'and'/'or' plus the six supported comparison operators."],"exampleFix":"// before\nlambda x: not x.active\n// after\nlambda x: x.active == False","handlingStrategy":"validation","validationCode":"import ast\ntree = ast.parse(filter_lambda_src, mode=\"eval\")\nassert not any(isinstance(n, ast.UnaryOp) for n in ast.walk(tree)), (\n    \"Filter lambdas must not use unary -, +, ~, or not\"\n)","typeGuard":"import ast\n\ndef filter_has_no_unaryops(src: str) -> bool:\n    tree = ast.parse(src, mode=\"eval\")\n    return not any(isinstance(n, ast.UnaryOp) for n in ast.walk(tree))","tryCatchPattern":"try:\n    results = await collection.vectorized_search(vector=v, options=opts)\nexcept NotImplementedError as e:\n    if \"Unary\" in str(e):\n        # rewrite 'not x.flag' as 'x.flag == False'\n        ...","preventionTips":["Replace 'not x.flag' with 'x.flag == False'.","Pre-compute negated/signed values outside the lambda."],"tags":["chroma","vector-store","filter","lambda","not-implemented"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}