Skip to main content
Back to Blog
Guide
2026-07-14

How to Tell Whether a RAG Failure Comes from Retrieval or Generation

Localize RAG defects with controlled context substitutions, claim evidence, retrieval labels, and release checks that separate retrieval from generation.

Diagnostic split showing retrieved evidence and generated claims in a controlled RAG evaluation workflow

A RAG retrieval vs generation failure cannot be localized from a bad final answer alone. The answer is downstream evidence: it may be wrong because the retriever omitted the governing passage, ranked noise above it, applied the wrong metadata filter, or supplied correct evidence that the generator ignored, distorted, or supplemented from unsupported memory. A reliable diagnosis changes one stage at a time, preserves every input and version, and compares the resulting claims against the same evidence contract.

Start with the complete RAG evaluation metrics guide, then use the companion guides on context precision, recall, and relevancy, high relevance with low faithfulness, and synthetic RAG testset generation. For the broader LLM quality model, read testing LLM applications; for an existing production pattern, use the RAG regression testing guide. Teams can also browse reusable QA instructions in /skills and automate browser evidence collection with the Playwright CLI skill.

The Diagnostic Question Is Causal, Not Merely Statistical

A low aggregate metric tells you that a system missed an expectation. It does not prove which component caused the miss. Retrieval and generation are coupled: generation quality depends on what retrieval supplied, while retrieval may be judged through a generated reference or an LLM evaluator. If the observation crosses both stages, it is not yet a component diagnosis.

The practical question is counterfactual: would the same generator answer correctly if it received a verified evidence bundle, and would the production retriever return that evidence without help? Those are separate experiments. The first holds generation configuration constant and substitutes context. The second bypasses generation and evaluates ranked retrieval output against labeled evidence.

ObservationPlausible causeEvidence still neededDo not conclude yet
Correct answer with gold context, wrong answer end to endRetrieval path is implicatedProduction trace, relevant document IDs, filter and ranking outputThat the vector database itself is broken
Wrong answer with gold contextGeneration path or fixture is implicatedClaim trace, prompt, model settings, gold-context reviewThat retrieval is healthy in production
Required document retrieved below the context cutoffRanking or packing can cause omissionFull ranked list and final prompt contextThat embedding quality alone caused it
Correct document and passage reach the prompt, unsupported claim appearsGeneration is strongly implicatedExact prompt, response, claim support labelsThat every answer defect is hallucination
Both isolated stages pass but end-to-end failsIntegration or transformation defectSerialized prompt, truncation, deduplication, orderingThat metrics are inconsistent

This table is a triage map, not a theorem. A mislabeled reference can make a healthy retriever look wrong. A stale source can make a faithful generator return an answer that is no longer operationally correct. A grader can disagree with human reviewers. Diagnosis requires raw artifacts, not only scores.

Version and Reproducibility Baseline

This guide was checked on July 14, 2026. The current PyPI release is Ragas 0.4.3. Its modern metrics live under ragas.metrics.collections, accept direct keyword arguments, and return a MetricResult whose numeric result is available through .value. The Ragas migration guide recommends experiment-oriented workflows instead of new uses of the legacy evaluate() and sample-based metric methods.

Promptfoo's current RAG guide also recommends testing document retrieval separately from generated output. Its context assertions can read static test context or extract context from a provider response with contextTransform. These tools support the workflow below, but neither library knows your authoritative document set, access policy, freshness rule, harm model, or release tolerance. Pin tool, model, prompt, corpus, index, and fixture versions in every result.

Record at least this run identity:

{
  "case_id": "leave-policy-effective-date-014",
  "query": "When does the revised parental leave policy apply?",
  "corpus_revision": "hr-handbook-2026-07-01",
  "index_revision": "hr-prod-shadow-2026-07-13.2",
  "retriever_config": "hybrid-v7-top20-rerank5-pack3",
  "prompt_revision": "answer-with-citations-v12",
  "generator": "provider/model-version",
  "grader": "provider/model-version",
  "expected_source_ids": ["hr-leave-2026-section-2"],
  "run_id": "ci-8421-case-014"
}

Do not replace an immutable model identifier with a marketing alias if the provider exposes a pinned version. If only an alias is available, save the date, provider response metadata, and repeated-run distribution. Reproducibility means another reviewer can reconstruct the conditions and evidence, not that a probabilistic output must be byte-identical.

Define an Evidence Contract Before Running Metrics

Each diagnostic fixture needs more than a question and an expected sentence. Define the facts that must be supported, the sources that are allowed to support them, the sources that are relevant but insufficient, and the response behavior when evidence is absent or contradictory.

For a policy question, a useful fixture includes:

  1. A stable case ID and user-visible query.
  2. The authoritative source document IDs, revisions, and relevant spans.
  3. Required atomic facts, such as effective date, eligible population, and exception.
  4. Acceptable alternate wording, without requiring one exact generated sentence.
  5. Distractor documents that are topically close but superseded, regional, or incomplete.
  6. Expected filters, permissions, and tenant boundaries.
  7. The desired abstention or clarification behavior when required evidence is unavailable.
  8. A risk label that determines whether a miss blocks a release or starts an investigation.
Fixture fieldRetrieval useGeneration useFailure it exposes
Relevant document IDsCalculate deterministic top-k inclusion and rankConfirm citations point to allowed evidenceMissing, misranked, or fabricated sources
Required claim listIdentify passages needed for coverageCheck every answer claim and required answer elementPartial context or incomplete answer
Superseded distractorsTest ranking and freshness filtersTest resistance to conflicting old textStale-source preference
Access labelsTest metadata and authorization filtersPrevent use of unauthorized contextCross-tenant or role leakage
No-answer expectationVerify empty or insufficient retrievalVerify abstention instead of inventionConfident answer without evidence

Human reviewers should validate the evidence contract independently of the system under test. If the reference answer was generated from the same RAG pipeline, it can preserve the same omission or false claim and create circular approval.

Capture the End-to-End Trace First

Run the failing case once without modifying the system. Capture every boundary so later substitutions are comparable:

  • Original user input after conversation resolution.
  • Query rewrites, decomposed subqueries, and filters.
  • Candidate IDs with raw retrieval scores.
  • Reranked IDs and scores, if a reranker is used.
  • Chunks after deduplication, packing, and token-budget truncation.
  • Exact context delivered to the generator, in order.
  • System instruction, answer prompt, tool output, and generation settings.
  • Final answer, citations, latency, token usage, and evaluator results.

Do not log restricted text indiscriminately. Store access-controlled references or approved redacted snippets when the corpus contains personal, regulated, or confidential data. The requirement is traceability, not uncontrolled duplication.

Separate the candidate list from the final prompt context. A relevant chunk can appear at rank three and still disappear because a parent-document expansion, deduplicator, tokenizer estimate, or context packer removed it. Calling that a retrieval success hides the integration defect that the generator actually experienced.

Run the Controlled Substitution Matrix

Use four runs with the same fixture. Keep temperature, seed when supported, prompt revision, model identifier, output parser, and evaluator configuration fixed.

RunContext sourceGeneratorWhat it isolates
A: productionProduction retrieval and packingProduction generatorReproduces user-visible behavior
B: gold-context substitutionHuman-verified minimal evidenceSame generator and promptWhether generation can use sufficient evidence
C: retrieval-onlyProduction ranked outputNo answer generationRank, coverage, filters, freshness, authorization
D: context perturbationGold context plus controlled distractor or missing spanSame generator and promptSensitivity to noise, conflicts, and absent evidence

Run B must replace the exact final context payload, not merely insert a desired document earlier in the pipeline. Otherwise a later transform may still remove it. Keep the gold bundle minimal but sufficient: include every required supporting span and the metadata the prompt normally receives, without leaking the expected final wording into an artificial instruction.

Run C should use deterministic labels where possible. Check whether every required source ID appears within the operational cutoff, its rank, whether an explicitly irrelevant source precedes it, and whether filters removed an authorized source. An LLM relevance grader may complement those labels for semantic edge cases, but a known document ID does not need a probabilistic judge.

Run D tests the response contract. Remove one required span and expect abstention or a bounded partial answer. Add a superseded but topically similar passage and expect the system to prefer the current source or expose the conflict. Add irrelevant text without changing relevant evidence and observe whether the answer acquires unsupported claims.

Implement a Framework-Neutral Diagnostic Harness

The component boundary should return structured data. The following Python uses dependency injection rather than a library-specific RAG API, so adapters can wrap any retriever and generator. It records both the production run and a gold-context substitution under the same configuration.

from dataclasses import dataclass
from typing import Callable, Sequence


@dataclass(frozen=True)
class Chunk:
    source_id: str
    text: str
    rank: int


@dataclass(frozen=True)
class Case:
    case_id: str
    query: str
    required_source_ids: frozenset[str]
    gold_context: tuple[Chunk, ...]


def diagnose(
    case: Case,
    retrieve: Callable[[str], Sequence[Chunk]],
    generate: Callable[[str, Sequence[Chunk]], str],
) -> dict:
    retrieved = tuple(retrieve(case.query))
    production_answer = generate(case.query, retrieved)
    gold_answer = generate(case.query, case.gold_context)
    retrieved_ids = {chunk.source_id for chunk in retrieved}

    return {
        "case_id": case.case_id,
        "required_sources_retrieved": sorted(
            case.required_source_ids.intersection(retrieved_ids)
        ),
        "missing_required_sources": sorted(
            case.required_source_ids.difference(retrieved_ids)
        ),
        "retrieved": [chunk.__dict__ for chunk in retrieved],
        "production_answer": production_answer,
        "gold_context_answer": gold_answer,
    }

This harness deliberately does not assign a root cause. It creates evidence for a reviewer or a separate assertion layer. Add claim-support labels, required-answer checks, and run identity outside the adapter. Do not infer that gold_context_answer is correct merely because it differs from production; evaluate it against the same claim contract.

For stochastic generators, run each condition several times and retain every output. Compare failure rates or score distributions rather than selecting the best answer. The number of repeats should follow observed variance and release risk, not a universal constant.

Add Metric Evidence without Letting It Replace the Experiment

Ragas context precision assesses whether relevant chunks are ranked ahead of irrelevant chunks. Context recall evaluates whether retrieved context supports the claims in a reference. Faithfulness evaluates whether claims in the response are supported by retrieved context. These metrics answer different questions, and their model-assisted variants inherit evaluator variance.

A useful evidence bundle includes both deterministic and model-assisted results:

EvidencePreferred methodWhy it mattersLimitation
Required source in top kID comparisonDirectly tests known retrieval expectationRequires curated source labels
Required claim represented in contextHuman label or context recallDetects evidence coverage gapsDepends on reference completeness
Relevant chunks ranked earlyContext precision plus rank inspectionDetects noisy orderingRelevance labels or judge can be wrong
Answer claims supportedFaithfulness plus claim ledgerDetects unsupported generationDoes not prove source truth or freshness
Answer addresses user intentAnswer relevancy or rubricDetects evasive or incomplete answersDoes not prove factual correctness

Promptfoo can keep retrieval and answer checks in one reviewable configuration while still treating them separately. This example assumes the provider returns an object with answer and documents; adapt paths to the real response shape and calibrate thresholds on labeled local data.

tests:
  - description: revised leave policy uses current evidence
    vars:
      query: When does the revised parental leave policy apply?
    assert:
      - type: javascript
        value: |
          const ids = output.documents.map((doc) => doc.id);
          return ids.includes('hr-leave-2026-section-2');
      - type: context-recall
        value: The revised policy applies from 1 September 2026.
        contextTransform: output.documents.map((doc) => doc.text).join('\n\n')
        threshold: 0.9
      - type: context-faithfulness
        contextTransform: output.documents.map((doc) => doc.text).join('\n\n')
        threshold: 0.9
      - type: answer-relevance
        threshold: 0.8

The numbers above illustrate configuration syntax, not recommended defaults. Establish release values by comparing metric outcomes with independent human labels, measuring evaluator repeatability, and assigning different tolerances to different risk slices. A single global threshold can conceal a serious failure in a small but regulated slice.

Interpret Controlled Outcomes

If production retrieval misses required evidence and the same generator succeeds with gold context, the retrieval path is the leading cause. Inspect query rewriting, embedding input, lexical and vector fusion, metadata filters, tenant scope, freshness, reranking, deduplication, and context packing in that order. Preserve the failing trace before rebuilding an index, because rebuilding can destroy evidence.

If gold context still produces an unsupported or incomplete answer, inspect generation. Verify that the context is actually serialized into the prompt, the instruction defines how to handle conflicts and absent facts, the output parser retains citations, and the model is not asked to combine incompatible sources. Create an atomic claim ledger and identify exactly which required claim was omitted or which answer claim lacked support.

If retrieval-only labels pass and gold-context generation passes but end-to-end fails, focus on the seam. Common defects include escaping that empties a context field, token truncation, wrong chunk ordering, a stale cache, mismatch between retrieved IDs and fetched bodies, a prompt variable bound to another case, or an authorization layer replacing content after evaluation.

If both isolated stages fail, log two defects unless evidence shows a shared cause. A stale corpus can create both missing retrieval labels and an incorrect reference. A malformed query can impair retrieval and misstate the user's intent to generation. Fixing only the visible answer may leave the retrieval regression intact.

Use the Diagnosis in CI and Release Decisions

CI should run a small deterministic localization set on every relevant change and a larger distributional suite on scheduled or release jobs. Tag fixtures by component, source, language, role, query complexity, freshness, and harm. Run impacted slices when a chunker, embedding model, reranker, filter, prompt, generator, or corpus revision changes.

Block immediately on hard invariants such as unauthorized source retrieval, missing required source IDs for critical policy cases, fabricated citations, or unsupported high-risk claims. Treat model-assisted score movement as an investigation signal until calibrated. Require the candidate to beat or match the baseline by slice, not only in a global average.

Store the substitution result with the failure. A CI message that says "faithfulness 0.62" forces the next engineer to reconstruct the experiment. A useful message says that the required source disappeared after reranking, gold context restored all required claims in four of five repeated generations, and the index revision changed in the candidate build.

Common Diagnostic Mistakes

Judging retrieval from the final answer. A generator may answer from prior knowledge even when retrieval failed, or ignore good context. Inspect ranked sources directly.

Calling any relevant chunk a retrieval pass. Retrieval must provide enough evidence inside the final context budget, not merely one topically related paragraph somewhere in the candidate list.

Using the expected answer as hidden context. Gold context should contain source evidence, not a sentence crafted to force the expected wording. Otherwise the substitution tests prompt leakage rather than generation ability.

Changing multiple variables during substitution. Switching the model, prompt, temperature, and context together destroys causal value. Change one boundary at a time.

Treating faithfulness as correctness. A response can faithfully repeat an outdated or incorrect source. Validate source authority, revision, and business truth separately.

Assuming a score names the defect. Context recall can fall because a reference has unsupported claims. Context precision can vary with relevance judgments. Read the reasons and raw examples.

Ignoring permissions. Gold evidence that the production identity is not allowed to retrieve is not a valid expected source for that user. Authorization belongs in fixture design.

Limits of This Method

Controlled substitution localizes a failure to an operational boundary; it does not automatically find the underlying line of code. It is weaker when retrieval and generation are jointly trained, when generation invokes tools or additional retrieval, or when conversation memory silently changes the query. Expand the trace to every evidence-producing step in those systems.

Gold context also has limits. Human reviewers may omit a necessary passage, disagree about source authority, or encode hindsight into the fixture. Review high-impact fixtures with domain owners and version them like code. Model-based metrics can reduce review effort but cannot establish the ground truth they are asked to judge.

Diagnostic Checklist

  • Reproduce the failure with pinned corpus, index, retriever, prompt, model, and grader identities.
  • Save query rewrites, filters, ranked candidates, packed context, prompt, response, and citations.
  • Label required source IDs, required claims, distractors, access rules, and no-answer behavior.
  • Evaluate retrieval without generation.
  • Replace final context with a verified minimal evidence bundle while holding generation fixed.
  • Remove required evidence and add controlled distractors to test expected degradation.
  • Trace every answer claim to a supplied span or label it unsupported.
  • Calibrate model-assisted metrics against human judgments by risk slice.
  • Report the localized boundary and evidence, not a score-only root-cause claim.
  • Add the case to component and end-to-end regression suites after the defect is fixed.

FAQ: RAG Failure Diagnosis

Can answer correctness alone distinguish retrieval from generation failure?

No. A correct answer can come from model memory despite failed retrieval, and an incorrect answer can appear despite perfect evidence. Inspect retrieval output directly and rerun the same generator with verified context.

What is the strongest evidence that retrieval caused the failure?

The production trace lacks required authorized evidence, retrieval-only checks confirm the omission or misranking, and the unchanged generator reliably succeeds when the final context is replaced with validated evidence. This implicates the retrieval path but still requires inspection of rewriting, filtering, reranking, and packing to find the implementation cause.

What if the required document was retrieved but the answer is wrong?

Confirm that the relevant span survived fetching, deduplication, ordering, and token packing into the exact prompt. If it did, trace answer claims against that span and inspect generation. A document ID in an early candidate list is not proof that the model received usable evidence.

Does low faithfulness always mean a generation defect?

It means the evaluator found answer claims unsupported by the supplied context. The cause may be generation, a malformed context extraction, an incomplete trace, ambiguous claims, or grader error. Review the claim-level evidence before assigning ownership.

Should gold context contain only one chunk?

Only if one chunk supports every required fact and preserves necessary qualifiers. Prefer the smallest sufficient bundle, but do not remove definitions, exceptions, dates, or provenance that a reasonable answer needs.

How many repeated generations are enough?

There is no universal count. Measure variance for the model and case type, then choose repetitions that can detect a release-relevant change within budget. Retain all outputs and avoid selecting only the best run.

Can Promptfoo or Ragas identify the root cause automatically?

They can produce retrieval, context, response, and faithfulness evidence. Root-cause localization still depends on controlled substitutions, trustworthy fixtures, raw traces, and knowledge of the system boundary. A metric name is not a causal diagnosis.

When should this become a blocking CI test?

Make deterministic safety, authorization, required-source, and citation invariants blocking as soon as they are stable. Promote model-assisted thresholds only after calibration shows acceptable agreement and variance for the relevant slice.

Conclusion

Diagnosing a RAG failure is an experiment-design problem. Capture the full trace, evaluate ranked retrieval against labeled evidence, replace the final context with a verified bundle, and hold generation constant. Then trace each answer claim back to supplied text. That sequence separates missing or mispacked evidence from a generator that fails to use evidence, while preserving enough detail to find the real defect and prevent its return.