Wrong-Document RAG Answers: Check Your Chatbot's Metadata Filter Before Reranking A developer documented a debugging approach for multi-tenant RAG chatbots that answer from the wrong merchant's documents, tracing the root cause to a missing or misspelled tenant filter in the retrieval stage rather than to reranking or generation. The writeup recommends logging every retrieved document ID alongside its tenant metadata, asserting a plausible result count at the retrieval boundary before fallback logic runs, and running a negative test proving one tenant can never retrieve another's document. It includes TypeScript transport code that wraps a vector-query route with a retrieval guard and retries 429 responses up to four times, honoring Retry-After with 250 ms exponential backoff. An e-commerce reranker cannot repair a candidate set that already contains another merchant's documents. Inspect retrieval first. A missing or misspelled tenant filter is the usual reason a multi-tenant RAG chatbot answers from the wrong document. TL;DR: Log every retrieved ID and its tenant metadata, reject implausible result counts, and run a negative test that proves one tenant can never retrieve another tenant's document. Only after that invariant passes should you trade retrieval quality against latency. The failure sits one stage earlier than it appears. RAG grounds generation in material selected by a retriever. If foreign catalog content enters that selection, prompt edits and reranking weights operate on the wrong evidence. A fluent answer can make the retrieval defect harder to see, but it cannot turn the foreign document into an allowed one. Here is the system as a diagram in words: shopper query - tenant predicate - vector candidates - relevance reranker - answer. Put the observation point between candidates and reranking. That is where the service still has enough structure to prove what happened: the requested tenant, returned document IDs, stored tenant values, result count, and elapsed time. No trace, no diagnosis. Treat tenant isolation and relevance as different classes of requirement. Isolation is a pass/fail invariant. Relevance is an optimization within the allowed tenant corpus. Latency is a budget shared by retrieval and reranking. Mixing those three leads teams to widen retrieval when the correct move is to repair a predicate. Before instrumentation, the trace often says only search completed . Support sees the wrong product in the answer, while engineering has no way to distinguish four plausible causes: retrieval admitted a foreign document, ranking promoted it, generation cited it incorrectly, or a zero-result fallback broadened the search. After instrumentation, one structured event answers the first and most important question. It records the expected tenant alongside every candidate's ID and tenant metadata. Keep raw query text out when policy requires it; a request ID and a stable query hash can join stages without placing shopper text in the event. A typo needs an explicit guard. If documents store tenant id but the query uses tenantId , the filter can silently match nothing. An empty candidate list may look harmless until fallback logic runs. Assert a plausible result count at the retrieval boundary, before fallback or generation can hide the signal. The following TypeScript calls the verified vector-query route and wraps its response with the retrieval guard. Put the discovery-generated request JSON in VECTOR QUERY BODY ; this keeps the copyable transport code exact without inventing fields that are not declared here. It retries 429 responses up to four times, honors Retry-After , and uses a 250 ms exponential backoff when the server does not provide one. type Candidate = { id: string; score: number; metadata: { tenant id?: string; sku?: string }; }; type RetrievalTrace = { requestId: string; expectedTenant: string; elapsedMs: number; resultCount: number; candidates: Array<{ id: string; tenantId?: string; score: number; } ; }; const wait = milliseconds: number : Promise