---
number: 12135
title: >-
  fix(ai): KB query survives ChromaDB HNSW "Error finding id" on type filter
  (#12133)
author: neo-opus-ada
state: CLOSED
createdAt: '2026-05-28T13:29:32Z'
updatedAt: '2026-05-28T13:50:38Z'
closedAt: '2026-05-28T13:50:38Z'
mergedAt: null
head: feature/kb-type-filter
base: dev
url: 'https://github.com/neomjs/neo/pull/12135'
---
Authored by Claude Opus 4.7 (Claude Code) as @neo-opus-ada. Session provenance: lane-claim A2A `MESSAGE:ed3d314e` (#12133).

FAIR-band: **operator-directed pickup** (assigned with #12132 this session, superseding the standing "no new items" hold). Author-lane pickup discipline N/A for directed work.

Resolves #12133

`ask_knowledge_base` / `query_documents` with a non-`'all'` `type` built a ChromaDB metadata `where` filter (`whereClause = {type}`) that trips the HNSW index's "Error finding id"; `type='all'` (no `where`) worked. Empirically reproduced 3× this session (including after an orchestrator restart). This degraded the `ticket-create` / `ticket-intake` duplicate sweep, which relies on `type='ticket'`.

`QueryService.queryDocuments()` now wraps `collection.query()`: on the HNSW "Error finding id" it retries unfiltered (over-fetched `nResults`) and post-filters the result chunks by the original `where` criteria (`type` + `tenantId`) inside the existing scoring loop. A stale index segment can no longer take down typed queries. `npm run ai:defrag-kb` rebuilds the index as the durable index-level remedy.

Evidence: L1 (bug reproduced 3× empirically; `node --check`; surgical try/catch + in-loop post-filter) → L2 required (runtime: a typed query succeeds via the fallback when the HNSW index trips). Residual: runtime verification + a mock-based fallback unit test (see below). [#12133]

## Deltas from ticket
- Implemented option 3 (graceful fallback) over option 2 (id prefilter): prefiltering would need a manual similarity pass (Chroma `query` takes no id restriction), whereas the fallback reuses the existing scoring loop. Option 1 (defrag) is the operational remedy, noted in the code + commit.

## Test Evidence
- `node --check` clean.
- The fallback is unit-testable by mocking `ChromaManager.getKnowledgeBaseCollection()` so `collection.query()` throws "Error finding id" on the `where` call then returns on the unfiltered retry. I did not add it in this commit — the HNSW error is index-state-dependent and the method has several injected deps (`ChromaManager` / `TextEmbeddingService` / `RequestContextService`). Flagging as a follow-up I can add on review if wanted.

## Post-Merge Validation
- [ ] `ask_knowledge_base(query, type='ticket')` returns results without "Error finding id" (verify both pre- and post-`ai:defrag-kb` to distinguish stale-index vs query-path).

## Cross-family review
Per §6.1 needs a cross-family (Gemini) Approved review before merge; routing once CI is green.
