RAG & GraphRAG7 min read

Why Your RAG Pipeline Is Lying to You

Most RAG pipelines retrieve wrong chunks 30-40% of the time. Here's how to catch it.

Carolina Fogliato

March 9, 2026

Here's an uncomfortable truth: your RAG pipeline is probably retrieving the wrong information a third of the time.

Not wrong enough to crash. Not wrong enough to obviously fail. Just wrong enough to produce confident-sounding responses that are subtly, dangerously incorrect.

I've audited dozens of RAG implementations. The pattern is consistent: teams build pipelines, test them on a few happy-path examples, declare success, and ship. Six months later, users are complaining that the system "doesn't really work" and nobody knows why.

The problem isn't the LLM. It's retrieval. And almost nobody is measuring it.

The Hidden Failure Mode

Let me show you what I mean.

Scenario: Customer Support RAG

Knowledge base: 10,000 documents. User asks: How do I reset my password?

What happens:

  1. 1. Query gets embedded
  2. 2. Vector search finds "similar" chunks
  3. 3. Top 5 chunks go to the LLM
  4. 4. LLM generates an answer

What you see: A reasonable-looking response about password reset.

What you don't see:

The retrieved chunks were actually about:

  • Chunk 1: Password policy requirements (not reset instructions)
  • ⚠️Chunk 2: Account recovery (close, but different process)
  • Chunk 3: Password reset (correct!)
  • Chunk 4: Two-factor authentication setup (wrong)
  • Chunk 5: Password expiration policy (wrong)

The LLM saw one relevant chunk out of five. It improvised with its parametric knowledge to fill the gaps. The answer looks right but contains details that aren't in your knowledge base.

This happens 30-40% of the time in typical RAG deployments.

Why Nobody Catches This

Three reasons this failure mode persists:

Reason 1

You're Only Testing End-to-End

Most teams test by asking questions and checking if the answer seems reasonable. This tests the entire pipeline—retrieval, augmentation, and generation—as a black box. When the answer is wrong, you don't know why. Was it bad retrieval? Bad prompting? LLM hallucination?

You need to test retrieval separately.

Reason 2

LLMs Are Good at Sounding Confident

When the LLM gets mostly-wrong context, it doesn't say "I'm not sure." It generates a plausible answer using whatever scraps of relevance it found plus its training knowledge.

The response sounds authoritative. Users trust it. The failure is invisible.

Reason 3

Retrieval Metrics Aren't in Your Dashboard

You're tracking:

  • • Response latency
  • • Token usage
  • • User satisfaction (maybe)
  • • Error rates

You're NOT tracking:

  • • Retrieval precision
  • • Retrieval recall
  • • Chunk relevance scores
  • • Context utilization

If you don't measure retrieval quality, you don't know when it's failing.

How to Catch It

Here's the evaluation framework I use:

Step 1: Build a Retrieval Test Set

Create a dataset of queries paired with the correct source documents.

retrieval_test_set = [
    {
        "query": "How do I reset my password?",
        "relevant_doc_ids": ["doc_123", "doc_456"],
        "relevant_chunks": ["chunk_123_2", "chunk_456_1"]
    },
    {
        "query": "What's the refund policy for annual subscriptions?",
        "relevant_doc_ids": ["doc_789"],
        "relevant_chunks": ["chunk_789_3", "chunk_789_4"]
    },
    # 50-100 examples covering your key use cases
]

How to Create This

  • • Sample real user queries from logs
  • • Have a human identify the correct source documents
  • • Map to specific chunks

Yes, this is manual work. It's worth it. Start with 50 examples covering your most important queries.

Step 2: Measure Retrieval Quality

For each test query, run your retrieval and measure:

def evaluate_retrieval(test_set, retriever, k=5):
    results = []

    for test in test_set:
        # Run retrieval
        retrieved = retriever.retrieve(test["query"], top_k=k)
        retrieved_ids = [chunk.id for chunk in retrieved]

        # Calculate metrics
        relevant_set = set(test["relevant_chunks"])
        retrieved_set = set(retrieved_ids)

        # Precision: What fraction of retrieved chunks are relevant?
        precision = len(relevant_set & retrieved_set) / len(retrieved_set)

        # Recall: What fraction of relevant chunks did we retrieve?
        recall = len(relevant_set & retrieved_set) / len(relevant_set)

        # Hit rate: Did we get at least one relevant chunk?
        hit = len(relevant_set & retrieved_set) > 0

        # MRR: Where does the first relevant chunk appear?
        mrr = 0
        for i, chunk_id in enumerate(retrieved_ids):
            if chunk_id in relevant_set:
                mrr = 1 / (i + 1)
                break

        results.append({
            "query": test["query"],
            "precision": precision,
            "recall": recall,
            "hit": hit,
            "mrr": mrr
        })

    return results

Key Metrics & Targets

MetricWhat It MeasuresTarget
Hit Rate% of queries with at least 1 relevant chunk>95%
Precision@k% of retrieved chunks that are relevant>60%
Recall@k% of relevant chunks that are retrieved>80%
MRRAverage rank of first relevant chunk>0.7

If your hit rate is below 90%, you have a serious problem. If precision is below 50%, you're flooding the LLM with noise.

Step 3: Analyze Failure Patterns

Don't just measure—understand why retrieval fails.

Pattern 1

Semantic Confusion

Query about "password reset" retrieves chunks about "password policy"—semantically similar, functionally different.

Pattern 2

Missing Context

The relevant information spans multiple chunks, but retrieval only gets part of it.

Pattern 3

Keyword Mismatch

User says "cancel subscription" but docs say "terminate service"—semantic gap.

Pattern 4

Freshness Issues

Retrieved chunks are from outdated documents.

Pattern 5

Popularity Bias

Frequently accessed content gets retrieved even when not relevant.

The Most Common Problems (and Fixes)

Problem 1: Chunks Are Too Small

Symptom: High recall, low precision. You're retrieving relevant content, but each chunk lacks context.

Why it happens: Aggressive chunking (200-300 tokens) splits logical units of information.

Fix: Increase chunk size to 500-800 tokens. Use semantic chunking that respects document structure.

Problem 2: Chunks Are Too Big

Symptom: Low precision, high noise. Retrieved chunks contain relevant info buried in irrelevant content.

Why it happens: Large chunks (1000+ tokens) mix multiple topics.

Fix: Decrease chunk size. Use hierarchical retrieval—retrieve big chunks, then re-rank smaller segments.

Problem 3: No Chunk Overlap

Symptom: Important information at chunk boundaries gets missed.

Why it happens: Adjacent chunks don't share context.

Fix: Add 10-20% overlap between chunks.

Problem 4: Embedding Model Mismatch

Symptom: Semantically relevant chunks don't surface.

Why it happens: Your embedding model wasn't trained on your domain. "Cancel" and "terminate" might not be close in embedding space.

Fix:
  • • Try different embedding models (e.g., text-embedding-3-large vs voyage-2)
  • • Fine-tune embeddings on your domain
  • Add keyword search as a fallback (hybrid search)

Problem 5: No Query Preprocessing

Symptom: Conversational queries don't match document language.

Why it happens: Users ask "How do I change my password?" but docs say "Password Reset Procedure."

Fix: Rewrite queries before embedding. Use LLM to convert to document-style language.

Problem 6: No Metadata Filtering

Symptom: Retrieving from wrong document categories.

Why it happens: A question about "Enterprise pricing" retrieves chunks from "Starter pricing" docs—semantically similar, wrong context.

Fix: Add metadata filters before vector search (category, version, date, etc.).

A Retrieval Debugging Checklist

When retrieval quality drops, run through this:

  • Check embedding model performance on your domain

    Run same queries through different models. Look for systematic gaps.

  • Analyze chunk boundaries

    Are logical units split? Is overlap sufficient?

  • Review failure patterns

    Semantic confusion? → Better embeddings or query rewriting
    Missing context? → Larger chunks or parent retrieval
    Wrong category? → Metadata filtering

  • Test hybrid retrieval

    Add BM25/keyword as fallback. Compare hit rates.

  • Check for stale content

    Are outdated docs still indexed? Is freshness weighted in ranking?

  • Examine edge cases

    Queries with typos. Multi-part questions. Negations ("NOT including...").

Quick Wins to Implement Today

If you do nothing else:

1

Create 50 test queries

with labeled relevant documents

2

Measure hit rate and precision

on your current retrieval

3

Add hybrid search

vector + keyword as a safety net

4

Log every retrieval

for later analysis

5

Review 10 random retrievals per week

manually

That's a few hours of work. It will save you months of debugging mysterious answer quality issues.

RAG isn't just "add search to your LLM." It's a retrieval problem that happens to use an LLM for generation.

The retrieval community has decades of research on this. Precision, recall, ranking, evaluation—these are solved problems. The RAG ecosystem has mostly ignored them.

Don't make that mistake.

Build evaluation into your pipeline from day one.

Start measuring. Start improving. Stop lying.

Building RAG systems and want help getting retrieval right?

Let's talk

This is one of the most common problems we fix.

Newsletter

RAG patterns and retrieval optimization—every Tuesday.

Join 2,500+ engineers and leaders getting practical AI implementation insights.

Subscribe to AI That Ships

Your Privacy Matters

We use cookies to enhance your experience, analyze traffic, and serve targeted ads.

By clicking "Accept All", you consent to all cookies. Cookie Policy