9 Minutes
Rubber Duck Debugging: How to Find and Fix Logic Bugs
Fix Bugs Faster! Log Collection Made Easy
Rubber duck debugging allows us to discover our own coding errors by retracing our steps. Instead of relying on complex black-box tools, we simply explain our own logic until the problem reveals itself.
This is one of the most straightforward debugging techniques around, and it can be easily enhanced by AI tools. This guide will show you how to do this, giving you:
- A basic rubber duck debugging regime.
- An overview of the pitfalls to avoid.
- A list of prompts you can drag-and-drop into your preferred AI platform.
By the end of this guide you’ll be ready to implement rubber duck debugging in your own testing regime, and understand all the pitfalls to avoid. Let’s get into it.
What is rubber duck debugging?
The concept of rubber duck debugging comes from The Pragmatic Programmer by Andrew Hunt and David Thomas, and it’s exactly what it sounds like: we take a piece of code and explain it line-by-line to a rubber duck (well, an imaginary rubber duck).
The duck never answers. That’s the point.
When we force ourselves to explain each step, hidden assumptions surface. We spot the logic gaps that may otherwise have gone undetected.
Today, we can apply the same method using AI tools like ChatGPT, Claude, or Gemini.
- We explain what the code should do.
- We walk through what it actually does.
- We identify where the logic breaks.
So our confusion turns into structured thinking. And the more structured our thought process, the faster we can root out problems.
Why rubber duck debugging works
When debugging ‘silently’, it’s easy to rush, right? We’re usually working in sprints, so it’s only natural that we rush towards the finish line.
Rubber duck debugging forces us to slow down. Each part of the logic suddenly becomes easier to follow and evaluate.
- We start reasoning step-by-step instead of making assumptions.
- It’s easier to track what the code is doing.
- We can highlight differences between expected and actual behavior.
- There’s less of the unfocused trial-and-error.
This turns unclear issues into specific, traceable problems and helps us identify breaks in logic, rather than simply using our best guess.

The traditional rubber duck debugging method
Ever since Hunt and Thomas published their book in 1999, rubber duck debugging has relied on this simple six-step framework.
- Take the smallest piece of code with the issue: Focus only on the relevant function or block to avoid distractions.
- State what the code is supposed to do: Describe the expected behavior in plain language, out loud or by writing it down (if you’re in an office, the latter option might be preferable!)
- Go through the code line by line: Explain what each line does and how it contributes to the final result.
- Track the data as it moves through the code: Follow variables, inputs and outputs step by step.
- Compare expected vs actual behavior: Identify where the result starts to differ from what should happen.
- Isolate the exact point of failure: Once the mismatch is clear, the bug is usually close to that point.
This process may feel slow, but it often leads to faster and more accurate debugging than jumping straight into fixes.
How to use AI for rubber duck debugging
You can use AI in two distinct ways:
- As a listener while you explain the code.
- As a tool that explains the code back to you.
The first approach is the closest to the traditional method, but both approaches have the same core purpose: to help AI clarify what the code is actually doing and where it might break.
Using AI as a listener to explain and validate logic
Here, AI becomes an invisible, very intelligent duck. Your role as the human in the loop stays largely unchanged.
- Describe what the code should do: Start by explaining the expected behavior in simple terms.
- Walk through the code step by step: Explain each part clearly, as if teaching someone else.
- Ask AI to validate your reasoning: Check if your explanation is correct or missing something.
- Ask where the logic might fail: Let AI point out weak assumptions or unclear steps.
- Refine and test your understanding: Use the feedback to clarify the problem before making changes.
This approach keeps control on your side while using AI to challenge your thinking.
Using AI to explain your code and uncover bugs
This approach flips the process. Instead of explaining the code, you let AI do it first.
- Provide a focused code snippet: Share only the relevant part of the code.
- Ask AI to explain the logic step by step: Get a clear breakdown of what the code is doing.
- Compare AI explanation with expected behavior: Check where the interpretation differs from what should happen.
- Identify inconsistencies or missing cases: Look for gaps, incorrect assumptions, or unclear logic.
- Use follow-up questions to go deeper: Ask about edge cases, failure points, or alternative implementations.
This method is useful when the code is unfamiliar or when it’s hard to clearly explain it yourself. But remember to keep the snippets small and focused when you’re writing the prompts. The clearer the input, the more useful the output.
Best AI prompts for rubber duck debugging
Start with a master prompt to set the behavior, then use follow-up prompts to guide the session step by step.
IMPORTANT: Add your code at the end of each prompt when using them.
Master prompts (start here)
| Goal / Situation | Prompt |
|---|---|
| Use AI as a classic rubber duck | You are my rubber duck. I will explain my code step by step. Do not give solutions. Only point out unclear reasoning, contradictions, or missing steps. Ask questions when something is not clear. |
| Use AI as an active rubber duck | Act as a rubber duck for debugging. As I explain my code, validate my reasoning, highlight incorrect assumptions, and point out where logic might break. Do not jump to fixes unless I ask. |
| Let AI explain the code first | Act as a rubber duck and explain this code step by step in plain English. Highlight assumptions, potential issues, and unclear logic. |
| Avoid guessing or hallucinations | Act as a rubber duck debugger. Only use information present in the code. If something is unclear or missing, say it explicitly instead of guessing. |
Follow-up prompts during debugging
| Goal / Situation | Prompt |
|---|---|
| Understand what the code does | Explain this code step by step in plain English. |
| Check expected vs actual logic | Based on this code, what is the expected output and what could go wrong? |
| Identify assumptions | What assumptions does this code make about inputs, state, or environment? |
| Find potential bugs | Where could this logic fail or produce incorrect results? |
| Detect missing edge cases | What edge cases are not handled here? |
| Simplify logic | Rewrite this logic in a simpler and clearer way without changing behavior. |
| Trace execution | Walk through this code with an example input and show each step of execution. |
| Debug unexpected output | This produces unexpected results. List possible causes and where to investigate. |
| Validate reasoning | I think this works like this: [your explanation]. Is that correct? If not, explain why. |
| Suggest tests | What test cases would validate this logic? |
These prompts work best with small, focused snippets. The clearer the input, the more useful the output.
Common mistakes when using rubber duck debugging
Rubber duck debugging is simple, but small mistakes can make it much less effective. These are the most common issues to avoid.
| Mistake | Why it’s a problem |
|---|---|
| Explaining too quickly | Skipping steps defeats the purpose of the method and hides where the logic actually breaks |
| Not stating expected behavior | Without a clear goal, it’s hard to detect when the code goes wrong |
| Jumping to fixes too early | Fixing before understanding often leads to new or repeated bugs |
| Working with too much code at once | Large code blocks reduce clarity and make it harder to isolate the issue |
| Being vague in explanations | Generic descriptions don’t expose the exact logic or flow of the code |
| Ignoring actual outputs or errors | Assumptions without checking real behavior can lead in the wrong direction |
| Trusting AI responses blindly | AI can be wrong or incomplete, so results always need verification |
| Using it as a shortcut instead of a process | The value comes from structured thinking, not quick answers |
Avoiding these mistakes keeps the method focused and makes it much more effective.
When to use rubber duck debugging in real projects
Rubber duck debugging is most useful when the issue is unclear but likely tied to logic or understanding rather than infrastructure or tooling.
- Logic bugs where the code runs but produces incorrect results.
- Unexpected outputs that don’t match what the code should do.
- Complex conditionals or nested logic that are hard to follow.
- Refactoring code where behavior must stay consistent.
- Understanding unfamiliar codebases or legacy code.
- Debugging edge cases that are not immediately obvious.
- Situations where “this should work” but doesn’t.
- Reviewing your own code before asking for help.
It’s especially effective early in the debugging process, when the goal is to understand the problem before attempting a fix.
How to combine rubber duck debugging with logs and real user data
Rubber duck debugging helps clarify how code is supposed to work and where the logic might break, but it doesn’t show what actually happens during execution.
In real projects, bugs often depend on real inputs, environments, and user behavior. This is where logs and real data become essential.
Use rubber duck debugging to structure your reasoning, then validate it with real execution data.
Tools like Bugfender make this process easier by providing logs, errors, and device context directly from real users.
Frequently asked questions about rubber duck debugging
Can rubber duck debugging help with complex systems or large codebases?
Yes, but only if the problem is broken down into smaller parts.
Trying to explain an entire system at once reduces clarity.
It works best when focusing on one function, flow, or issue at a time.
Is rubber duck debugging useful even if there are no visible errors?
Yes. It’s often used when code runs without crashing but produces incorrect or unexpected results.
Explaining the logic helps uncover subtle issues that aren’t obvious from errors alone.
Should rubber duck debugging be used before or after trying other debugging methods?
It’s most effective early in the process.
Using it first helps clarify the problem and avoid wasted time on random fixes. It can also be used later when debugging gets stuck and the issue is still unclear.
Can rubber duck debugging slow down development?
It may feel slower at first, but it usually saves time overall.
Spending a few minutes explaining the code often prevents longer debugging sessions caused by misunderstandings or incorrect fixes.
Expect The Unexpected!
Debug Faster With Bugfender