"Login is broken." Claude Code changes something and login works, but signup now throws. It fixes signup, and the session cookie stops being set. Forty minutes later there are eleven modified files, none of the original error message is left anywhere, and you can no longer say which change was the one that helped.

This is the most expensive failure mode in AI-assisted work, and it starts with a symptom handed over without a way to reproduce it.

The idea

An agent given a symptom and no reproduction will guess, and a guess that half works is worse than one that fails outright: it changes the error, which looks like progress. The way out is to make each attempt falsifiable and cheap to undo. Reproduce the failure yourself, shrink it, read the actual error text, change one thing, and check that one thing.

text
  the circle                          the line
  ----------                          --------
  report the symptom                  reproduce it yourself, on demand
        |                                     |
  agent guesses a fix                 shrink it to the smallest failing case
        |                                     |
  a different error appears           read the real error, top line and file path
        |                                     |
  paste the new error ---+            change exactly one thing
        ^                |                    |
        +----------------+            did that one thing fix it?
                                          |            |
                                        yes           no
                                          |            |
                                       commit    revert to the last
                                                 good commit and restate

How it works

Reproduce before you ask. A failure you cannot trigger on demand cannot be verified as fixed, so every "fixed it" that follows is unfalsifiable. The reproduction is a recipe: the exact steps, the exact input, the exact error text.

Read the real error rather than the summary of it. The first line of a names what went wrong, and the topmost line mentioning a file you wrote is usually where to look. Paste it in full. An agent handed "it errors" invents a cause; an agent handed the trace reads one.

One change at a time. When three edits ship together and the symptom moves, you have learned nothing about which edit did it. Ask for the cause before the fix: "explain why this happens, and do not change anything yet" costs one turn and saves the guess.

Anthropic's Claude Code guidance sets the stopping rule: after two failed corrections, start fresh with a better prompt built from what you learned. By then the is full of failed approaches, and the model keeps re-reading its own wrong turns as if they were context.

Reverting is the part people skip. Version control makes the whole session disposable, which is what lets you throw away a bad direction instead of defending it. Version control, plainly covers the mechanics.

What to do

  1. Commit before you start. git commit -am "before login fix" gives you a known good point, and git reset --hard HEAD returns to it exactly.
  2. Write the reproduction into the request: steps, input, and the error pasted in full. Ask for the cause first and the fix second.
  3. After the second failed fix, revert. Open a fresh session and describe the bug plus everything you ruled out, rather than continuing the conversation that accumulated the failures.

Where it breaks

Some bugs will not reproduce on your machine. Timing bugs, bugs that need real traffic, and bugs that only appear on the production database are real, and the answer there is better evidence rather than more attempts: logs from the moment it failed, the actual request, the actual data.

Reverting also destroys good work when you have not been committing. The cost of the revert is set by how long ago your last commit was, which is the real argument for committing more often than feels necessary.

And a clean reproduction can still point at the wrong layer. When the smallest failing case involves a library you did not write, check its version and its release notes before assuming your own code is at fault.