On this page
How to Debug AI-Generated Code: A Complete System for When You Don't Understand What the AI Wrote
Your AI wrote 300 lines and you don't know what any of it does — and now it's broken. Here's a repeatable debugging system: isolate, bisect, instrument, explain. No prior understanding required.
Quick answer
- Don’t try to understand the whole file. Narrow to one function that’s broken.
- The system: isolate the failing unit → bisect to find which change broke it → instrument to see actual values → explain the bug back to the AI to get a targeted fix.
- This works when you don’t understand the code. It only requires understanding the bug.
The problem: AI wrote it, you don’t understand it, and it’s broken
This is the universal vibecoder debugging experience. The AI generated a 300-line function three days ago. It worked. Now it doesn’t. You don’t know what the function does — the AI seemed to understand it, so you never read it carefully. And now you’re staring at a stack trace in code you didn’t write.
The instinct is to paste the error back into the AI and ask “fix this.” That sometimes works. But when it doesn’t — when the AI produces a different broken version, or fixes one thing and breaks two more — you need a system.
The four-step debugging system
Step 1: Isolate — narrow the problem to one function
You don’t need to understand the whole codebase. You need to find the single function where behavior diverges from expectation.
# Don't try to understand this entire file.
# Find the function that's returning wrong data.
# Good: narrow the problem
# "The function get_user_orders() returns an empty list but the database has 5 orders."
# Bad: try to understand everything
# "This module has 12 functions and one of them is wrong somewhere."How to isolate:
- Follow the stack trace to the call site
- Find the last function that was called before the error or wrong output
- That’s your target
If there’s no stack trace (wrong output, no error), add print statements at the boundaries between functions to see where the data changes from correct to incorrect.
# Instrument boundaries to find where data goes wrong
print(f"orders before filter: {orders}") # [1,2,3,4,5]
orders = filter_orders(orders)
print(f"orders after filter: {orders}") # [] ← problem is in filter_ordersStep 2: Bisect — find which change broke it
If the code worked before and doesn’t now, use git bisect to find the exact commit that introduced the bug. This works even if you don’t understand the code — you only need a yes/no test for whether the bug exists.
# Start bisect
git bisect start
# Mark current commit as bad (bug exists)
git bisect bad HEAD
# Mark a known-good commit (bug didn't exist)
git bisect good <commit-hash-from-when-it-worked>
# Git checks out a commit in the middle. Test it:
# - Run the app, trigger the bug, see if it happens
# - If bug exists: git bisect bad
# - If bug doesn't exist: git bisect good
# Repeat until git identifies the exact commit
git bisect reset # when doneFor a walkthrough with AI-generated code specifically, see the companion guide: How to Find Which AI-Generated Change Broke Your App Using Git Bisect.
Step 3: Instrument — see what’s actually happening
You’ve isolated the function and know which commit broke it. Now instrument the function to see actual values — not what you assume is happening.
def calculate_discount(order_total, user_tier):
# Instrument entry
print(f"calculate_discount called: total={order_total}, tier={user_tier}")
if user_tier == "premium":
discount = order_total * 0.2
elif user_tier == "basic":
discount = order_total * 0.1
else:
discount = 0
# Instrument exit
print(f"calculate_discount returning: {discount}")
return discountCommon AI mistakes that instrumentation reveals:
- Wrong type: the function expects a number but received a string (
"100"not100) - Silent None: a function returns
Noneinstead of a value, which propagates silently - Empty iterable: a filter removes everything because the condition is inverted
- Wrong default: a dict lookup falls through to the wrong default value
Step 4: Explain — ask the AI to fix the specific bug, not the whole file
Now you know:
- Which function is broken
- What input it receives
- What it actually returns
- What you expected it to return
Give this to the AI as a targeted prompt:
The function `calculate_discount` in `src/pricing.py` returns 0
when called with order_total=100 and user_tier="basic".
Expected: 10 (10% of 100)
Actual: 0
The bug is likely in this function. Show me the fix without
changing anything else in the file.This is the opposite of “fix this.” It’s “this specific function, these specific values, what’s wrong?” The AI’s response will be surgical instead of a rewrite.
The full debugging loop
Bug discovered
│
▼
1. Isolate: find the one function returning wrong data
│
▼
2. Bisect (if regression): find the commit that broke it
│
▼
3. Instrument: add prints/debugger at function boundaries
│
▼
4. Explain to AI: "function X, input Y, expected Z, got W — what's wrong?"
│
▼
AI produces targeted fix
│
▼
Apply fix → run tests → verify
│
▼ (still broken)
Loop back to step 3 with new informationWhen the AI can’t fix it
Sometimes the AI’s fix doesn’t work — or makes things worse. This usually means the bug is architectural (not a single-function error) or context-dependent (the AI doesn’t have enough information). In that case:
- Narrow further: split the function into smaller pieces and test each
- Compare with a working version: if you have a known-good state (git stash), compare the working vs broken logic
- Add more instrumentation: add logging at every branch point (
if/else) to see which path is taken - Ask the AI to explain, not fix: “Explain what this function does, step by step.” Understanding the code is often faster than getting the AI to fix it blindly.
Specific debugging guides
This system breaks down into focused techniques depending on what’s broken. Each of these is a standalone guide:
- How to Debug AI-Generated API Logic — When your endpoint returns wrong data or wrong status codes. How to trace request → handler → response when you didn’t write the handler.
- How to Debug AI-Generated Database Queries — When queries return wrong results, N+1 problems, or nothing at all. How to extract and test the AI’s SQL.
- How to Find Which AI-Generated Change Broke Your App Using Git Bisect — The full git bisect walkthrough for AI-generated code, including writing a bisect test when you don’t know the codebase.
Where this bites vibecoders
The debugging loop above is the difference between a vibecoder who ships and one who stalls. When you don’t understand the code, the natural response is to paste the error back into the AI and hope. That works for simple bugs. For everything else, isolate → bisect → instrument → explain. This turns “I don’t know what’s wrong” into “this function, this input, this expected output — what changed?”
Where AI coding assistants get this wrong in debugging
- Accepting “fix this” and rewriting 300 lines instead of fixing one function.
- Not asking for expected vs actual values — it guesses at the bug instead of diagnosing it.
- “Fixing” the bug by changing behavior elsewhere, creating a cascade of new failures.
- Producing a fix that works for the specific test case but breaks other inputs.
Checklist
- Isolate the problem to one function before involving the AI
- If regression:
git bisectto find the exact commit - Instrument function boundaries to see actual input/output values
- Ask the AI: “function X with input Y returns Z, expected W — what’s wrong?”
- Apply fix → run tests → verify → commit
- Never accept a multi-function rewrite as a bug fix
FAQ
What if I don’t understand the code at all?
That’s the normal starting point with AI-generated code. Don’t try to understand the whole file — narrow the problem to one function, add print statements or a debugger at its entry and exit, and compare actual vs expected values. Understanding the bug is enough; understanding the whole module can come later.
Should I ask the AI to debug its own code?
Yes, but give it the specific failure: “This function returns [] when I expect [1,2,3]. Here’s the input, the actual output, and the expected output. What’s wrong?” Don’t ask “can you fix this?” — the AI will rewrite the whole file. Pin it to the specific failure.
What if git bisect points to a commit with 20 changed files?
Narrow further. Run git diff <bad-commit>^ <bad-commit> -- <path/to/broken/function> to see only the changes in the file containing the broken function. If that’s still too much, bisect within the commit: comment out sections of the diff until you find the specific change that introduced the bug.
Related topics
- How to Debug AI-Generated Code When You Don’t Understand It
- How to Debug AI-Generated API Logic
- How to Debug AI-Generated Database Queries
- How to Find Which AI-Generated Change Broke Your App Using Git Bisect
- How to Review AI-Generated Code Like a Senior Engineer
- How to Write Your First Unit Test