fix: guard Layer3.search_raw against None doc/meta from ChromaDB (#1011)
Same class of bug as #1007: ChromaDB's query() can return None in the documents and metadatas arrays when a drawer's HNSW vector entry exists but its metadata/document rows haven't been materialized. The code in Layer3.search_raw (mempalace/layers.py) calls meta.get("wing", ...), meta.get("room", ...), meta.get("source_file", ...) directly without null safety, so it raises: AttributeError: 'NoneType' object has no attribute 'get' Two-line defensive coercion matching the pattern in #1009 / PR #999 for searcher.py: meta = meta or {}, doc = doc or "". The hit still appears with its real distance; source/wing/room fall back to their fallback values where the metadata row is missing. Frequently hit on chromadb 1.5.x (root cause #1006). Even after the chromadb floor lands (#1010), partial-state results remain possible during interrupted mines and schema upgrade boundaries, so the guard is worth having on its own. Fixes #1011.
This commit is contained in:
@@ -281,6 +281,8 @@ class Layer3:
|
||||
|
||||
lines = [f'## L3 — SEARCH RESULTS for "{query}"']
|
||||
for i, (doc, meta, dist) in enumerate(zip(docs, metas, dists), 1):
|
||||
meta = meta or {}
|
||||
doc = doc or ""
|
||||
similarity = round(1 - dist, 3)
|
||||
wing_name = meta.get("wing", "?")
|
||||
room_name = meta.get("room", "?")
|
||||
@@ -327,6 +329,13 @@ class Layer3:
|
||||
_first_or_empty(results, "metadatas"),
|
||||
_first_or_empty(results, "distances"),
|
||||
):
|
||||
# ChromaDB may return None for doc/meta when a drawer's HNSW entry
|
||||
# exists but its metadata/document rows haven't been materialized
|
||||
# (partial-flush states, mid-delete, schema upgrade boundaries).
|
||||
# Degrade gracefully — the hit still appears with real distance;
|
||||
# storage fields show their fallback where content is missing.
|
||||
meta = meta or {}
|
||||
doc = doc or ""
|
||||
hits.append(
|
||||
{
|
||||
"text": doc,
|
||||
|
||||
Reference in New Issue
Block a user