Reproduce the Bug and Shrink It
The hardest bugs are not the ones with error messages. They are the ones where the program runs fine and gives the wrong answer. There is no red text telling you where to look.
For these, professional developers follow the same two steps before they change anything: reproduce the bug reliably, then shrink it to the smallest piece of code that still shows it. These steps find most bugs on their own, and they make any help you ask for, from a person or an AI, far more effective.
What You'll Learn
- Why you must reproduce a bug before fixing it
- How to write down expected vs actual behavior
- How to shrink a bug to a minimal example
- How to use print statements to see what your code is really doing
Step 1: reproduce it
A bug you cannot reproduce is a bug you cannot confirm you fixed. Before changing any code, find exact steps that make the bug appear every time:
- Which input causes it? Does it happen with every input or only some?
- What exactly do you do to trigger it?
- What happens, and what did you expect to happen?
Write it down in one short note. This is useful for you, and it is exactly what an AI or a colleague needs later:
Input: ["Apple", "banana", "Orange", "kiwi", "egg"]
Expected: 3 words start with a vowel
Actual: the program says 1
The gap between expected and actual is the bug. Writing both down often makes the cause obvious.
Step 2: shrink it
Real programs are long. The bug is usually in a small part. Shrinking means removing everything that is not needed to show the problem:
- Start with the full programBug confirmed
- Remove a pieceDelete or comment out unrelated code
- Still broken?Yes: keep it removed. No: put it back
- RepeatUntil only the essential lines remain
Also shrink the input. If a list of 1,000 items gives the wrong result, does a list of 3 items still do it? Smaller inputs make the problem easier to see and easier to check by hand.
The result is called a minimal example. Very often, the bug becomes obvious while you are making one. When it does not, you now have a short, clear piece of code to show an AI, instead of your whole project.
Step 3: look inside with print
When code gives a wrong answer, you need to see what it is doing step by step. The simplest tool is a print statement (print() in Python, console.log() in JavaScript) placed inside the code to show the values as it runs.
Good places to print:
- Inside a loop, to see each value as it is processed.
- Before and after a condition, to see whether it was true.
- Just before a result is returned, to see what is actually being returned.
For example, if a count is too low, print each item and whether it was counted:
for word in words:
print(word, word[0] in "aeiou")
Output like Apple False shows the problem immediately: the check is failing for "Apple." Why? Because "A" is uppercase and the check only looks for lowercase vowels.
Remove your print statements once the bug is fixed, or they will clutter your output.
Your turn: find the wrong answer
This code should count how many words start with a vowel. It runs without errors but gives the wrong count. Add a print inside the loop to see what is happening, then fix it. The correct output is Vowel words: 3.
Notice what happened: no error, no AI, just making the code show its work. This is the same idea as asking a reasoning model to show its steps: once the steps are visible, the wrong one stands out.
Key Takeaways
- Reproduce first: find exact steps and inputs that trigger the bug every time.
- Write down input, expected, and actual. The gap between expected and actual is the bug.
- Shrink the code and the input to a minimal example. The cause often becomes obvious along the way.
- Use print statements in loops, around conditions, and before returns to see what the code is really doing.
- A minimal example with expected vs actual is also the best thing to give an AI when you ask for help.

