Prompt template · Code
Debugging prompt for a stack trace
Rank likely root causes from an error and stack trace, say what to check first, and suggest the smallest fix. Free to copy, or open it in the prompt builder to fill the variables and get the exact API request.
293 tokens unfilled · 412 with the example below · o200k_base (GPT-4o and later)
Template
The prompt
Paste this into a chat window and replace each {{variable}}, or open it in the prompt builder to fill them in a form. Sections are marked with XML tags, which every major model reads well.
You are an experienced {{language}} engineer helping debug a failure. You form hypotheses from evidence and say how confident you are.
<context>
The error and stack trace:
<stack_trace>
{{stack_trace}}
</stack_trace>
The code at the frames that belong to us:
<code>
{{code}}
</code>
What happened before the error, and what has changed recently:
<circumstances>
{{circumstances}}
</circumstances>
</context>
<constraints>
- Separate what the trace proves from what you are inferring.
- Give up to three hypotheses, most likely first, each with the evidence for it and a quick check that would confirm or rule it out.
- Distinguish the frame where the error surfaced from the frame where the bug is. They are often different.
- Propose the smallest change that fixes the root cause. Don’t rewrite unrelated code or add broad try/except blocks that hide the error.
</constraints>
<output_format>
- Root cause (most likely), in one sentence
- Hypotheses: numbered, each with evidence, confidence (high, medium, low) and a check
- Fix: a code change for the most likely cause
- Prevent it: one test or guard that would have caught this
</output_format>
<task>
Work out the most likely root cause of this error. Tell me what to check to confirm it, and the smallest fix.
</task>For an API call: system prompt and user message
With a system prompt, the role, constraints and output format stay fixed across calls (and can be cached), while the context and task go in the user message.
You are an experienced {{language}} engineer helping debug a failure. You form hypotheses from evidence and say how confident you are.
<constraints>
- Separate what the trace proves from what you are inferring.
- Give up to three hypotheses, most likely first, each with the evidence for it and a quick check that would confirm or rule it out.
- Distinguish the frame where the error surfaced from the frame where the bug is. They are often different.
- Propose the smallest change that fixes the root cause. Don’t rewrite unrelated code or add broad try/except blocks that hide the error.
</constraints>
<output_format>
- Root cause (most likely), in one sentence
- Hypotheses: numbered, each with evidence, confidence (high, medium, low) and a check
- Fix: a code change for the most likely cause
- Prevent it: one test or guard that would have caught this
</output_format><context>
The error and stack trace:
<stack_trace>
{{stack_trace}}
</stack_trace>
The code at the frames that belong to us:
<code>
{{code}}
</code>
What happened before the error, and what has changed recently:
<circumstances>
{{circumstances}}
</circumstances>
</context>
<task>
Work out the most likely root cause of this error. Tell me what to check to confirm it, and the smallest fix.
</task>Variables
What to put in each variable
- {{language}}
- The language and runtime, such as Node.js 22 or Python 3.13.
- {{stack_trace}}
- The full error message and stack trace, unedited. Remove secrets such as tokens in URLs, but keep file names and line numbers.
- {{code}}
- The source of the frames from your own code, especially the top one. Library frames usually don’t need their source.
- {{circumstances}}
- What triggered it, how often it happens, and recent changes: a deploy, an upgrade, new data. “Started after upgrading pg from 8.11 to 8.13” is often the whole answer.
Use
When to use it
Use it when an error isn’t obvious from its message: an exception deep in a library, a null that shouldn’t be null, a failure that only happens in production. The structure works for any language with stack traces, and for test failures with their assertion output.
If the error message already tells you the fix, such as a missing module, skip the template and fix it. And if the bug can’t be reproduced, say so in the circumstances; intermittent failures point to different causes (timing, shared state, data) than deterministic ones.
Structure
Why it’s structured this way
The three context sections mirror how an experienced engineer debugs: the evidence (trace), the code it points at, and what changed. The last one is the most underrated. Many production bugs are explained by a recent deploy or upgrade, and a model can’t know about it unless you say.
Asking for ranked hypotheses with checks, rather than a single answer, guards against the model’s tendency to commit confidently to the first plausible cause. Separating proof from inference makes it obvious which parts to verify, and the confidence label tells you whether to start with the check or go straight to the fix.
The rule about surfacing frame versus buggy frame addresses a classic mistake: a TypeError in a template is usually caused by bad data created much earlier. The ban on broad exception handling stops the most common bad fix, which makes the error disappear without fixing anything.
Example
A filled-in example
- {{language}}
Node.js 22 with TypeScript
- {{stack_trace}}
TypeError: Cannot read properties of undefined (reading 'email') at formatRecipient (src/mail/format.ts:14:22) at sendReceipt (src/mail/receipt.ts:31:18) at processOrder (src/orders/process.ts:88:5)- {{code}}
// src/mail/receipt.ts export async function sendReceipt(order: Order) { const customer = order.customer; // loaded with the order await mailer.send(formatRecipient(customer), render(order)); }- {{circumstances}}
Happens for about 1% of orders since yesterday’s deploy, which added guest checkout. Orders from logged-in users are fine.
What to look for. The trace surfaces in formatRecipient, but the circumstances point at the real cause: guest-checkout orders have no customer, so the fix belongs where guest orders are created or in sendReceipt, not in the formatter.
The complete filled-in prompt (412 tokens)
You are an experienced Node.js 22 with TypeScript engineer helping debug a failure. You form hypotheses from evidence and say how confident you are.
<context>
The error and stack trace:
<stack_trace>
TypeError: Cannot read properties of undefined (reading 'email')
at formatRecipient (src/mail/format.ts:14:22)
at sendReceipt (src/mail/receipt.ts:31:18)
at processOrder (src/orders/process.ts:88:5)
</stack_trace>
The code at the frames that belong to us:
<code>
// src/mail/receipt.ts
export async function sendReceipt(order: Order) {
const customer = order.customer; // loaded with the order
await mailer.send(formatRecipient(customer), render(order));
}
</code>
What happened before the error, and what has changed recently:
<circumstances>
Happens for about 1% of orders since yesterday’s deploy, which added guest checkout. Orders from logged-in users are fine.
</circumstances>
</context>
<constraints>
- Separate what the trace proves from what you are inferring.
- Give up to three hypotheses, most likely first, each with the evidence for it and a quick check that would confirm or rule it out.
- Distinguish the frame where the error surfaced from the frame where the bug is. They are often different.
- Propose the smallest change that fixes the root cause. Don’t rewrite unrelated code or add broad try/except blocks that hide the error.
</constraints>
<output_format>
- Root cause (most likely), in one sentence
- Hypotheses: numbered, each with evidence, confidence (high, medium, low) and a check
- Fix: a code change for the most likely cause
- Prevent it: one test or guard that would have caught this
</output_format>
<task>
Work out the most likely root cause of this error. Tell me what to check to confirm it, and the smallest fix.
</task>Models
Tips by model family
- Claude
On Claude Fable 5.1, Fable 5, Opus 5.5, Opus 5 and Sonnet 5.5, Anthropic says a prompt asking the model to write out its reasoning, for example in
<thinking>tags, may be declined. This template asks for evidence per hypothesis instead; for harder bugs, raise the effort setting. - Gemini
Google’s guide says Gemini 2.5 and 3 series models think internally, so they don’t need reasoning steps written in the response. For a hard bug, a plain “Think very hard before answering” can help instead.
- All models
Paste the whole trace. Truncated traces lose the frames that show where the bad value came from, and that is usually the part you need.
Related
Related templates and tools
- Summarise logsTurn a long log into a timeline, the distinct errors with counts, and the likely first failure.
- Explain codeA plain-English walkthrough of unfamiliar code at the reader’s level: purpose, flow, side effects and traps.
- Incident postmortemTurn a timeline and chat logs into a blameless postmortem: impact, causes, what went well and actions.
Edited the template? Compare your version with this one in the prompt diff, and count it for your model with the token counter. In the glossary: chain of thought. Browse all 29 prompt templates.