Debugging With AI Without Going in Circles: A Systematic Loop
AI debugging fails when you outsource the thinking; it works when you drive a tight hypothesis-and-evidence loop.
Everyone has had the session: you paste an error, the AI suggests a fix, it doesn't work, you paste the new error, it suggests another fix, and forty minutes later you're three theories deep, two of the changes contradict each other, and you no longer remember what the original state was. The model was confident the whole time. That confidence is exactly the trap.
The circling isn't caused by a weak model. It's caused by treating a debugger as an answer vending machine instead of as a reasoning partner in a loop you control. Debugging is a search over hypotheses, and the AI is good at generating hypotheses and terrible at knowing which one is true without evidence. Your job is to run the loop that produces evidence. Here's the loop.
Step 1: Establish the facts before asking for a fix
The most common mistake is asking "why is this broken and how do I fix it" in the same breath. That invites the model to jump straight to a fix for the most statistically likely cause, which may not be your cause. Separate observation from action. Start by giving it what's actually known and asking only for hypotheses:
Here's what I observe:
- Symptom: /checkout returns 500 intermittently, ~1 in 20 requests.
- It started after we deployed commit a3f2c1 yesterday.
- The 500s correlate with requests that have a coupon code.
- Stack trace: [paste].
Don't suggest a fix yet. List the 3 most likely causes,
ranked, and for each one tell me what evidence would confirm
or rule it out.This reframes the model from fixer to diagnostician. The "what evidence would confirm it" clause is the important part: it turns each hypothesis into something testable instead of something to blindly apply. Intermittent and "1 in 20" and "correlates with coupons" are the kind of facts that narrow the search dramatically, and they're facts the model can't guess.
Step 2: Test one hypothesis at a time, and report back what actually happened
The circling begins when you apply fix A, it doesn't obviously work, and you immediately apply fix B without confirming whether A did anything. Now you have two changes and no idea which mattered. Discipline here is unglamorous and decisive: change one thing, observe, report the real result.
When you report back, give the model the actual output, not your interpretation of it. "It still doesn't work" is nearly useless. "After adding the null check, the 500 is gone but now it returns an empty cart for coupon requests, here's the new log line" moves the search forward. The model reasons from evidence; feed it evidence, not vibes.
Step 3: Make it explain the mechanism, not just the fix
A fix you don't understand is a fix you can't trust, and it's how subtle bugs get papered over. When the model proposes a change, require the causal chain:
Before I apply that, explain the mechanism:
- exactly which line produces the wrong value
- why it only happens with a coupon code
- why it's intermittent rather than every time
If your explanation doesn't account for the intermittency,
your hypothesis is probably wrong.That last sentence is a genuinely useful filter. Many proposed fixes explain the symptom but not its shape. If a bug is intermittent and the explanation would predict a constant failure, the explanation is incomplete, and applying the fix will "work" only until the real cause resurfaces. Forcing the model to reconcile its theory with every observed property catches this before you commit.
Step 4: Reduce, don't accumulate
When you're several exchanges in and nothing has landed, the instinct is to add more: more logging, more context, more speculative changes. The better move is to reduce. Ask the model to help you build the smallest reproduction:
We're not converging. Help me build a minimal repro instead.
What's the smallest input and setup that should trigger this,
and what's a single log line or assertion that would tell us
definitively whether the coupon value is wrong before it
reaches the payment call?A minimal repro does two things at once: it removes variables that were confusing the model, and it converts a fuzzy "sometimes 500s" into a deterministic test. Once you have a deterministic repro, the AI's hypotheses become checkable in seconds instead of arguable in paragraphs. Most stuck debugging sessions are really "we never pinned down the repro" sessions.
Step 5: Keep a running state so the session has a memory you trust
Long debugging chats drift. The model forgets that you already ruled out the cache theory in message four, and re-suggests it in message twelve. Rather than trusting the chat's memory, maintain a short ledger yourself and paste it back periodically:
State so far:
- RULED OUT: db connection pool (checked, pool is healthy).
- RULED OUT: caching (disabled cache, bug persists).
- CONFIRMED: coupon.discount is sometimes a string, not a number.
- OPEN: why is it a string only after the a3f2c1 deploy?
Given this, what's the next single thing to check?This is the antidote to circling. The ledger is ground truth; the chat history is not. It also forces you to notice when you're making progress versus spinning, because a session where the RULED OUT list isn't growing is a session that's stuck.
When to stop asking the AI and read the code yourself
There's a category the loop won't crack, and recognizing it saves hours. If a bug depends on runtime state the model can't see, race conditions, a value that's only wrong in production, a config that differs between environments, the model is guessing from an incomplete world no matter how good your prompts are. Symptoms that you've hit this: every hypothesis is plausible and none is confirmable, the fixes keep addressing the code you pasted rather than the state you can't paste, and the model starts repeating earlier suggestions.
At that point the productive move is to gather the runtime evidence yourself, add the logging, capture the actual production value, diff the environments, and bring that evidence back. The AI is excellent at reasoning over facts and poor at acquiring them. The division of labor that works: you get the observations, it generates and ranks the hypotheses, you run the tests, it explains the mechanism.
The loop, compressed
- State observations; ask for ranked hypotheses and the evidence that would confirm each. No fixes yet.
- Test one hypothesis. Report the actual result, not your read of it.
- Require the mechanism, and reject explanations that don't fit the bug's shape.
- When stuck, reduce to a minimal deterministic repro.
- Keep your own state ledger; paste it back so the session can't forget or loop.
Nothing here is specific to one tool; it works the same in Claude Code, Cursor, Copilot Chat, or a plain model window. The common thread is that you stay the one holding the hypothesis space and the evidence, and you use the model for what it's genuinely great at: generating candidate explanations faster than you can and explaining mechanisms once you've narrowed the field. Go in with that division of labor and the circling stops, because there's no longer an open loop for it to spin in.
A note on shelf life. AI products change fast. This guide deliberately focuses on the parts that stay true — how to judge a tool, what the trade-offs are — rather than ranking products that will have changed by the time you read it. Prices and feature claims should always be checked against the provider before you rely on them.