Debugging Code You Didn't Write and Don't Understand

The instinct is to hand the failure back to the agent. Without a reproduction that produces a plausible fix to a plausible cause — and two rounds later nobody understands the module at all.

A production bug in a module an agent wrote three weeks ago, that nobody on the team has read closely, is a situation that will become ordinary. It's worth having a method for it, because the instinct — ask the agent to fix it — frequently makes things worse.

Why the instinct backfires

Handing the failure back to an agent works when the problem is reproducible and mechanically checkable. When it isn't, you get a plausible fix to a plausible cause, and the plausible cause is often not the actual one.

The specific hazard: the agent will find a defect. Most code contains something improvable, and a search for a cause returns a candidate. Fixing it changes behavior, the symptom may shift, and now the system is different in a way nobody fully understands — with the original bug possibly still present.

⚠️ Two or three rounds of that and you have a module nobody understands and a history of speculative changes, which is materially worse than where you started.

The method

1. Reproduce before anything else. Nothing here works without a reproduction. This is the highest-value step and the one most often skipped under pressure, because reproducing is slow and speculating is fast.

A reproduction converts the whole problem into an oracle-driven one, at which point delegating becomes safe. Without it, every subsequent step is guessing — for you and for any agent you involve.

If you can't reproduce it, the work is making it reproducible: better logging, capturing the failing input, narrowing the conditions. That's the task, not the fix.

2. Read the code before asking about it. Not all of it — the path involved. This is the step people skip when they don't feel ownership of the module, and skipping it means you can't evaluate any explanation you're given.

You don't need to understand every line. You need enough of a model to tell a plausible explanation from a correct one.

3. Ask for an explanation, not a fix. ✅ The most useful first request is "explain how this code produces this behavior with this input" — the answer is checkable against the code in front of you, and it builds your model rather than substituting for it.

A fix, by contrast, arrives as a change you can't evaluate, which puts you back where you started.

4. Localize before repairing. Narrow to the smallest region reproducing the failure. Bisect the input, disable branches, add assertions. Mechanical, delegable, and it converts "somewhere in this module" into "these fifteen lines."

5. Write the failing test. Then, and only then, is fixing safe to delegate — there's an oracle, so a wrong fix fails visibly.

6. Understand why the fix works. If you can't explain it, you have a passing test and an unknown system. That's a deferred problem, not a solved one.

🔍 The specific trap of agent-written code

Agent-written code is typically idiomatic and locally sensible, which affects debugging in a particular way: it doesn't look wrong.

Human-written bugs often carry a tell — hurried code, an inconsistent style, an obviously tired shortcut. Generated code has uniform quality, so scanning for the suspicious part doesn't work. The defect is usually a correct-looking implementation resting on a wrong assumption, and assumptions aren't visible in code.

The adaptation: rather than looking for the wrong-looking line, look for the assumption. What does this code believe about its inputs, about ordering, about what can be null, about what the caller has already done? Then check each belief against reality. This is slower than scanning and it's the technique that actually works here.

💡 The prevention that matters

The situation is much easier when the module was reviewed properly when it was written. That's the argument for real review of agent output that has nothing to do with catching bugs at review time — it's that someone has a model of the code, and that model is what makes the eventual debugging tractable.

A module nobody ever read is a module nobody can debug quickly. The review cost is paid once; the debugging cost without it is paid every time.

The takeaway

Reproduce first — without it every step is speculation. Read the relevant path yourself before asking anything. Ask for explanations you can check rather than fixes you can't. Localize mechanically, write the failing test, and only then delegate the repair. And look for the wrong assumption rather than the wrong-looking line, because generated code doesn't advertise its defects.

Keep reading

Similar posts

Matched on shared tags and category — the more bars, the stronger the overlap with what you just read.