Mid · 7 chapters
Debugging a single bad output
Bisect the prompt, ablate context blocks one at a time, verify the chat template, check for truncation, re-run at temperature 0 vs N samples, diff against a known-good trace
A single unexplained bad trace can send days of prompt and retrieval changes in the wrong direction.
Read these first
What you will know
Take one bad output and find the cause without guessing
Record the rendered request, model settings, token counts, and a known-good trace so the conclusion can be reproduced rather than inferred from the visible text alone.
Bisect a prompt to find the instruction responsible
Instruction interactions can make the apparent culprit harmless in isolation, so verify the change with the same input and generation settings.
Ablate context blocks one at a time to find the one that mattered
A block may alter ordering, salience, or token budget even when its content is irrelevant, making ablation results sensitive to placement.
Check whether the retrieved context even contained the answer
A correct-looking retrieval score does not prove answer coverage; inspect the actual passages and confirm that truncation or formatting did not remove the evidence.
Separate a systematic failure from a sampling fluke by re-running
Temperature-zero repetition tests determinism, while multiple seeded samples reveal whether the observed output is merely low-probability behavior.
Chapters
- 1
Freezing a trace
A trace is the complete record of one exchange with a model, and it stops existing the moment the system around it moves. Freezing one means capturing the request exactly as it left your service — rendered template, model id and resolved snapshot, sampling parameters and seed, per-block token counts, finish reason — plus a known-good trace of the same shape to diff against, so that whatever you conclude about a single bad answer can be reproduced rather than argued.
- 2
Chat templates and the rendered request
A messages array is a client-library convenience; what the model receives is one sequence of token ids produced by a chat template. When that template is skipped — an instruction-tuned model behind a completion endpoint fed \"System: ... User: ... Assistant:\" — there is no system prompt at all, only prose in one undifferentiated turn. Render the same messages through apply_chat_template, diff the ids against what was sent, and read the envelope fields before the prose.
- 3
Answer coverage in retrieved passages
Similarity ranks chunks against a query and says nothing about whether any of them states the fact the answer needed. Before blaming a model for inventing a refund window, read the retrieved passages and check coverage — then separate the three places evidence goes missing: never ingested, ingested but not retrieved, or retrieved and then removed by a token budget or mangled by formatting on the way into the prompt.
- 4
Low-temperature replay and rate estimation
Two questions hide inside \"can we reproduce it\", and they need two different replays. A pinned low-temperature run establishes that your own stack produces a sane answer from the recorded bytes; twenty to thirty runs at production sampling, with the seeds recorded, estimate how often the bad output appears. One duplicate refund in thirty is a systematic defect with a low probability, and the rate is also what decides whether a single edited re-run counts as evidence in the chapters that follow.
- 5
Context ablation by substitution
Removing a retrieved block and re-running changes three things at once — its content, the position of everything below it, and several hundred tokens of budget — so a correct answer afterwards has three candidate explanations and one run. Swapping the block for a same-length neutral passage holds layout and budget fixed and varies only content, which is what stands between a real finding and a corpus-wide filter that reinstates the bug the next time ranking shuffles.
- 6
Instruction bisection
Halving a 900-token system prompt can make a refusal disappear while removing the one instruction that mentions safety does not, because instructions are not independent constraints. Delta debugging guarantees a minimal failing set, not a culprit, so the search continues into pairs among the survivors — and the technique differs from context ablation in what it holds constant, what it confounds, and what a positive result licenses you to change.
- 7
Promoting a trace into a change
Three prompt changes, each verified by re-running the trace that prompted it, cost four points of aggregate quality at the next release: every new instruction is global state that interacts with everything else, while nothing checked the cases nobody complained about. The gate that prevents it turns on a class rate — construct fifteen siblings of the failing input and measure how many fail — which is also what separates a tail sample from a trace that represents an entire input class.
External resources
- Debugging LLM Failures Systematically: A Field Guide for Engineerstianpan.co
A repeatable bisect-and-ablate procedure for one bad generation.
- Model Outputs Garbage: Debugging Bad Generationsinsiderllm.com
Maps symptoms to causes: template, sampling params, repetition, context loss.
- Context Window Overflow: Fix LLM Errors Fastredis.io
Why silent context eviction degrades answers with no error raised.
- How to Improve LLM Apps with Error AnalysisShaw Talebi
Method for taking one bad trace apart and finding which context caused it