You know the rubber duck debugging technique — explain your code to an inanimate object and the bug reveals itself. The same trick works on AI assistants, except the duck talks back.
I call it the Rubber Duck Prompt, and it has caught more silent bugs in AI-generated code than any linter I've used.
The Problem
AI assistants are confident. They'll hand you 200 lines of code that looks correct, passes a quick scan, and then breaks at 2 AM because of an edge case the model quietly assumed away.
The issue isn't that AI can't reason about edge cases — it's that you never asked it to show its reasoning.
The Pattern
After your AI generates code, add this follow-up prompt:
Walk me through every decision you made in that implementation:
1. Why did you choose this data structure?
2. What edge cases did you consider? Which ones did you skip?
3. What assumptions are you making about the input?
4. Where is this most likely to break?
That's it. Four questions. The answers will surprise you.
A Real Example
I asked an assistant to write a function that deduplicates a list of user objects by email address:
def dedupe_users(users):
seen = set()
result = []
for user in users:
if user['email'] not in seen:
seen.add(user['email'])
result.append(user)
return result
Looks fine. But when I applied the Rubber Duck Prompt, the assistant admitted:
- It assumed emails are always lowercase (they're not —
User@Example.com≠user@example.comin this code) - It kept the first occurrence, not necessarily the most recent one
- It assumed
user['email']always exists (no KeyError handling)
Three bugs, zero test failures, caught by asking "explain yourself."
Why This Works
Large language models have a hidden context of assumptions they don't surface unless prompted. When you force the model to articulate its decisions, two things happen:
- The model catches its own mistakes. Explaining a decision activates different reasoning paths than generating code.
- You catch what the model can't. Reading "I assumed emails are lowercase" is a red flag you wouldn't notice by reading the code alone.
Making It Automatic
I keep a rubber-duck.md template in my project root:
## Post-Generation Review
After generating any function/module, answer:
- What data structure did you pick and why?
- What are the top 3 edge cases? Did you handle all of them?
- What happens with empty/null/malformed input?
- Where would you put the first breakpoint if this broke in production?
I paste this into every code-generation session. It takes 30 seconds and saves hours.
When to Use It
- After any function longer than 20 lines
- Before committing AI-generated code to a shared branch
- When the assistant's output "looks right" but you can't articulate why
- Anytime you're about to skip a code review because you're in a rush
The Anti-Pattern
Don't ask "is this correct?" — the model will say yes. Ask "what did you assume?" — that's where the bugs live.
The Rubber Duck Prompt won't catch every bug. But it catches the category of bugs that are hardest to find: the ones hiding behind reasonable-looking code and unstated assumptions.
Try it on your next AI-generated function. The duck always knows more than it lets on.
Top comments (0)