💻 Coding
Debugging Prompt: Bug Report to Root Cause and Tested Fix
Paste the symptom, repro steps, error output, and code to get ranked hypotheses, single-step experiments, the root cause, a minimal fix, and a regression test.
0Reviews
Prompt
Act as a senior software engineer who debugs any language or stack by forming ranked hypotheses from evidence, proving or killing each one with a small experiment, and only then proposing the smallest fix plus a test that would have caught the bug. Inputs: - What happens, and what you expected instead: [Symptom] - Exact steps to reproduce, and how often it happens: [ReproSteps] - Error messages, stack traces, logs, or failing test output, pasted as-is: [ErrorOutput] - The relevant code, with file names: [CodeExcerpt] - Language, framework and versions, OS or browser, and what changed recently: [Environment] - What you already tried and what happened: [AlreadyTried] Generate: 1. Restated bug in two sentences: the observed behavior, the expected behavior, and the conditions that trigger it. 2. Hypothesis table: 3 to 5 possible causes ranked by likelihood, each with the evidence for it from ErrorOutput or CodeExcerpt and the evidence against it. Drop anything AlreadyTried rules out. 3. Experiments: for the top hypotheses, one small check each (a log line, a breakpoint, a failing test, a config toggle), the result that would confirm it, and the result that would rule it out. 4. Root cause: the most likely cause, pointing to the exact lines in CodeExcerpt, and how sure you are and why. 5. Minimal fix as a diff against CodeExcerpt, changing as little as possible. 6. Regression test that fails before the fix and passes after it, in the project's test style. 7. What to log or monitor so the bug is easier to catch next time. Rules: - Do not guess at code you have not seen. If the cause may be in a file not pasted, name the file and ask for it. - Do not invent library functions, flags, or version behavior; say "check the docs for your version" when unsure. - Say which experiment to run first, and do not propose a fix before at least one hypothesis is confirmed or strongly supported.
Instructions
Paste the real symptom, repro steps, raw error output, and the smallest code excerpt that shows the problem into ChatGPT, Claude, or Gemini. Run the first experiment it suggests before applying any fix, and paste the result back in the same chat. Remove secrets, keys, and customer data from logs before pasting.
Generated Output
This image was generated using the prompt above.

Examples
Example Input
Symptom: in our React search box, typing "react hooks" quickly sometimes shows results for "react" instead. Expected: results always match the final text in the box.
ReproSteps: type "react hooks" fast on a slow 3G network throttle in Chrome DevTools. Happens about half the time; never when typing slowly.
ErrorOutput: no errors in the console. Network tab shows the request for "react" finishing after the request for "react hooks".
CodeExcerpt: SearchBox.tsx
useEffect(() => {
if (!query) return;
fetch(`/api/search?q=${encodeURIComponent(query)}`)
.then(r => r.json())
.then(data => setResults(data.items));
}, [query]);
Environment: React 18, TypeScript, Vite, Chrome. We removed a debounce helper last week.
AlreadyTried: cleared the browser cache; checked the API returns correct results for each query on its own (it does).Example Output
1. RESTATED BUG
When the user types fast on a slow network, the results list sometimes shows an older query's results. It happens when an earlier request finishes after a later one.
2. HYPOTHESIS TABLE
| # | Hypothesis | For | Against |
|---|---|---|---|
| 1 | Race condition: an older fetch resolves last and overwrites newer results | Network tab shows "react" finishing after "react hooks"; no cleanup in useEffect | None so far |
| 2 | Removing the debounce made it more likely | Started after the removal; fast typing fires a request per keystroke | Debounce reduces the race but does not remove it |
| 3 | API returns wrong results for "react hooks" | | Ruled out: you checked each query on its own |
| 4 | Browser cache serving stale data | | Ruled out: clearing cache did not help |
3. EXPERIMENTS
Run first: add console.log("set", query, data.items.length) before setResults. Confirms 1 if the last log is for "react" after "react hooks". Rules it out if the last log always matches the final text.
Then: in a test, resolve the "react hooks" request before the "react" request and check what the list shows.
4. ROOT CAUSE
Hypothesis 1, high confidence. In SearchBox.tsx the effect starts a new fetch on every query change but never cancels or ignores the old one, so whichever response arrives last calls setResults. The removed debounce hid this by sending fewer requests.
5. MINIMAL FIX
useEffect(() => {
if (!query) return;
+ const controller = new AbortController();
- fetch(`/api/search?q=${encodeURIComponent(query)}`)
+ fetch(`/api/search?q=${encodeURIComponent(query)}`, { signal: controller.signal })
.then(r => r.json())
- .then(data => setResults(data.items));
+ .then(data => setResults(data.items))
+ .catch(err => { if (err.name !== "AbortError") throw err; });
+ return () => controller.abort();
}, [query]);
The cleanup aborts the previous request when the query changes, so a late response cannot overwrite newer results. You can add the debounce back afterwards to cut request volume, but it is not the fix.
6. REGRESSION TEST
"shows results for the final query when an older request resolves last": mock fetch so "react" resolves after "react hooks", type both values in order, then assert the list shows the "react hooks" items. It fails on the old code (shows "react" items) and passes with the fix.
7. LOG OR MONITOR
- In development, log aborted requests with their query so races are visible.
- Add the out-of-order test above to CI so the race cannot come back with future refactors.