AI Coding
The prompt for fixing broken code
You paste an error. Thirty seconds later four files have changed, something new is broken, and nobody can say which edit did it. A smarter single prompt will not save you here. Five small ones will, sent one at a time, each one holding back permission for the next.
5 prompts · copy-paste ready · works in any assistant
Why "fix this error" produces such bad fixes
Ask an assistant to fix something and it will. That is the problem. It is built to produce a plausible repair, and a plausible repair can be written without ever locating the fault. Nothing in "fix this error" says find out what is wrong first, so the diagnosis quietly gets skipped and you get an edit that looks like one.
Two habits make it worse. If guessing is allowed, it guesses, and a guess comes back sounding exactly like a fact. If editing widely is allowed, it edits widely: the fix, plus an import tidy, plus a rename, plus some hardening in a file you never mentioned. Once a change spans four files you have lost the ability to attribute anything to anything.
So the script below makes each step conditional on the one before it. Nothing gets edited until the error is understood, and nothing gets called fixed until the tests say so. On an easy bug that costs you four extra messages. On anything else it is the difference between twenty minutes and an afternoon.
Ask once
Ask five times
The five prompts, in order
Send one per message. Read the answer before you send the next one. If an answer trips a stop signal, repeat that step instead of moving on.
- 1
Read it back to me before you touch anything
Ban the edit. Ask for a plain-English translation of the error first.
Prompt 1Here is the full error. Do not touch the code yet. <paste the entire error, the stack trace, and the exact command you ran> Tell me in plain English what this error is saying. Which file and line is it pointing at, and what was the code trying to do at that moment? If any part of the trace is ambiguous, say so instead of filling in the gap.
Why this step exists
Plenty of bugs that get called mysterious are a message nobody read to the end. The trace already names the file and the line. Making the assistant restate it in plain words is a cheap check on whether it read the same error you did, and you find that out before it costs you a file. The "do not touch the code yet" clause is doing the real work here. Take it out and most assistants are editing before you have finished reading their first paragraph.
Send it again if
- The answer starts with "I've updated…". It edited first and explained afterwards.
- It describes a file that appears nowhere in the trace.
- The explanation has more jargon in it than the error did. Ask again, shorter.
- 2
What did we change since it last worked?
Get a file list out of git, not out of the model's memory of the chat.
Prompt 2Do not propose a fix yet. What has changed in this codebase since this last worked? List every file that changed, with one line on what changed in it. Use git — git log, git diff, git status — not your memory of our conversation. If you cannot tell when it last worked, say so and tell me what you need from me.
Why this step exists
Code that worked and now does not has changed. The error says where it broke, the diff says what broke it. Asking for git output rather than recollection matters more than it sounds: long sessions drop context, and an assistant will describe edits that never happened without a flicker of doubt. The file list doubles as your shortlist for step 3.
Send it again if
- You get a recap of the conversation instead of commits and paths.
- The paths do not exist. Ask it to run the command and paste the real output.
- 3
Three possible causes, ranked, with evidence
Force a comparison instead of a single confident guess. Ban guessing out loud.
Prompt 3Now give me three possible causes for this error, most likely first. For each one: name the specific file and line, state the evidence in the error or the diff that points to it, and say what I would expect to see if that cause were the real one. If a cause is a guess with no evidence behind it, leave it out and give me fewer than three.
Why this step exists
One cause is a guess in a good suit. Three of them, ranked against each other, drag the reasoning out where you can argue with it. "No guessing" is the load-bearing phrase: drop it and you get three fluent paragraphs about async timing that would fit any codebase ever written. Asking what each cause predicts also hands you a free test. If #1 says a config value is undefined, you can log it and know in ten seconds.
Send it again if
- The three causes are one cause rephrased three ways.
- A cause arrives with no line and no evidence. Strike it and ask for two.
- The ranking has no stated reason. Ask what makes #1 likelier than #2.
- 4
Fix the top cause only. One file. Diff first.
The narrowest possible change, shown to you before it lands.
Prompt 4Fix cause #1 only. One file. Nothing else. Show me the diff before you apply it. No refactors, no renames, no tidying of code you happen to dislike, no changes to any test. If fixing cause #1 genuinely requires touching a second file, stop and tell me why instead of doing it.
Why this step exists
This is the step that saves your afternoon. Left to itself, an assistant fixes the bug and also reorders the imports, renames a variable, and adds a little defensive code two files away. The suite goes red for a brand new reason and nothing is attributable to anything. One file keeps the change reversible: if it misses, you revert one thing and take cause #2 on a clean tree. Barring edits to tests is not paranoia either. A test quietly adjusted to match the broken behaviour is a fix that reports success.
Send it again if
- The diff spans more than one file. Reject it and ask which single file holds the fault.
- Any test file appears in the diff.
- It applied the change and then showed you what it did.
- The summary mentions a cleanup or a rename you never asked for.
- 5
Run the tests. Prove it. Prove nothing else broke.
Two claims, two pieces of evidence. Output, not adjectives.
Prompt 5Now run the tests. Show me the actual command and the actual output. Prove two things: the case that was failing passes now, and everything that passed before still passes. If no test covers this bug, write one that fails before your change and passes after, and show me both runs. "Should be fixed now" is not an answer — I want the output.
Why this step exists
"That should fix it" is the most expensive sentence in AI-assisted debugging. It costs you the next hour. Every fix makes two claims and only one of them usually gets checked; the second, that nothing else moved, is the one that comes back a week later. Where no test covered the bug, the fail-then-pass pair is what separates a fix from a coincidence. If your assistant cannot run commands, step 5 is yours. Run it, paste the output back, make it read the result.
Send it again if
- You get prose about what the tests would do instead of a terminal block.
- It ran one test file and called the suite green.
The whole script on your clipboard
Keep it in a scratch file or a snippet manager and send the blocks one at a time. It also holds up
pasted into a CLAUDE.md
or .cursorrules as a standing debugging policy.
--- Step 1: Read it back to me before you touch anything (send as its own message) --- Here is the full error. Do not touch the code yet. <paste the entire error, the stack trace, and the exact command you ran> Tell me in plain English what this error is saying. Which file and line is it pointing at, and what was the code trying to do at that moment? If any part of the trace is ambiguous, say so instead of filling in the gap. --- Step 2: What did we change since it last worked? (send as its own message) --- Do not propose a fix yet. What has changed in this codebase since this last worked? List every file that changed, with one line on what changed in it. Use git — git log, git diff, git status — not your memory of our conversation. If you cannot tell when it last worked, say so and tell me what you need from me. --- Step 3: Three possible causes, ranked, with evidence (send as its own message) --- Now give me three possible causes for this error, most likely first. For each one: name the specific file and line, state the evidence in the error or the diff that points to it, and say what I would expect to see if that cause were the real one. If a cause is a guess with no evidence behind it, leave it out and give me fewer than three. --- Step 4: Fix the top cause only. One file. Diff first. (send as its own message) --- Fix cause #1 only. One file. Nothing else. Show me the diff before you apply it. No refactors, no renames, no tidying of code you happen to dislike, no changes to any test. If fixing cause #1 genuinely requires touching a second file, stop and tell me why instead of doing it. --- Step 5: Run the tests. Prove it. Prove nothing else broke. (send as its own message) --- Now run the tests. Show me the actual command and the actual output. Prove two things: the case that was failing passes now, and everything that passed before still passes. If no test covers this bug, write one that fails before your change and passes after, and show me both runs. "Should be fixed now" is not an answer — I want the output.
What each step is actually protecting you from
Every step looks skippable in the moment. Here is the bill for skipping it.
| Step | Prevents | What skipping it costs |
|---|---|---|
| 1. Read it back | A fix aimed at the wrong line | You debug the model's misunderstanding for an hour before noticing it read the wrong frame of the trace. |
| 2. What changed | Hunting a bug that was never in the file you are staring at | The fault lives in a dependency bump or a config edit, and nobody looked there because the trace pointed somewhere else. |
| 3. Three causes | Confident single-cause tunnel vision | You implement the first plausible theory, it half-works, and now the symptom has moved instead of gone. |
| 4. One file, diff first | Collateral edits you did not ask for | Four files changed. Something new is broken. Neither of you can say which edit did it. |
| 5. Prove it | Fixes that exist only in the summary paragraph | You ship it. The bug comes back on Monday with a second one stapled to it. |
House rules
How to send them
One prompt per message
Paste all five at once and you have rebuilt the giant prompt you were trying to escape. The order is the technique. Each step hands out permission for the next one only after you have read the answer.
Paste the error whole
Full stack trace, the command you ran, versions if they are in play. Trimming it down to "the important bit" is you doing step 3 before step 1, because you have already decided which part counts.
If step 5 fails, go back to step 3
Not step 4. Revert first, then take cause #2 on a clean tree. A second fix stacked on a failed first one is how a one-line bug turns into an evening.
You only know what you changed on purpose
Lockfiles, generated files, environment variables and somebody else's merge are all changes you did not make and will not remember. Run step 2 anyway.
Start a fresh chat if it has already gone rogue
Ten messages of rewriting leaves the context full of its own bad theories, and it will defend them.
Questions
Which AI assistants does this work with?
All of them. It is plain text, not a feature, so it works the same in Claude Code, Cursor, Copilot Chat, Windsurf, or a browser tab with ChatGPT. Agentic tools that can run git and your test suite get more out of steps 2 and 5, because they can produce real output instead of asking you for it.
Is five prompts not slower than one?
It is slower than a one-shot fix that works, and much faster than the hour you spend untangling four files of unasked-for edits to find the original bug still sitting there. The cost lands on the easy bugs, which were never the problem.
What if the project has no tests?
Step 5 becomes: give me the exact command that reproduced the bug, run it, show me the output before and after. Then ask for one test covering the case you just fixed. A bug that reached production is the best argument you will ever get for the test that would have caught it.
Some bugs genuinely span more than one file. Does the one-file rule break those?
No, because the rule is not "never touch two files". It is "never touch two files silently". Step 4 tells the assistant to stop and explain if a second file is genuinely required, which gives you the chance to agree. What it kills is the drive-by refactor, which was the actual problem.
Can I put this in a rules file instead of pasting it every time?
Yes. CLAUDE.md, .cursorrules, or a saved prompt all hold it fine, and the "no guessing" and "one file, diff first" clauses are worth keeping permanently. Do it anyway as five messages when something is actually broken, though. A standing instruction shapes behaviour; a sent message forces a checkpoint you have to read.
Does telling a model "no guessing" actually stop it guessing?
Not completely. What it reliably changes is the shape of the answer: fewer confident paragraphs, more "I cannot tell these two apart without seeing X". That is the useful part. You get a standard to reject an answer against instead of a vague feeling that it sounds too sure of itself.
Something broken you cannot get past?
We build small tools and the automation behind them. If a bug has outlasted five prompts, tell us what it is doing.
Get in touch