When Your AI Feels Like a Junior Dev: The Growing Pains of Vibe Coding Tools
When Your AI Feels Like a Junior Dev: The Growing Pains of Vibe Coding Tools
Introduction
Have you jumped on the "vibe coding" bandwagon yet? If you haven't heard, vibe coding is all about coding alongside AI assistants like Cursor and Claude. These tools promise to make your coding smoother, faster, and maybe even a bit more fun. Sounds great, right?
Well, mostly. The reality is, sometimes my AI sidekick feels less like an expert coder and more like that enthusiastic junior dev fresh out of bootcamp. They're eager, helpful, and… prone to rookie mistakes.
Let me dive into some entertaining real-world examples showing how my vibe coding tools sometimes patch symptoms instead of truly solving problems.
Why Junior-Level Fixes Are a Big Deal
Every engineer knows the drill—junior devs have a knack for band-aid solutions. The code might "work," but lurking underneath are hidden tech debts, sneaky bugs, and the dreaded surprise outage at 2 AM. Unfortunately, many AI code assistants today behave exactly this way, fixing superficial symptoms without touching the root cause.
Example 1: The Mysterious Trailing Slash Bug
I encountered a production issue caused by an extra /
at the end of a GET parameter. Here's the prompt I initially gave to Claude:
"A GET call to the prod server with URL
http://app.obico.io/unsubscribe_email/?list=account_notification%2F&unsub_token=%5BFiltered%5D
results in aKeyError: 'notify_on_account_notification/'
."
Claude's initial diagnosis seemed straightforward:
Based on my analysis, I understand the issue. Here's what's happening:
The unsubscribe URL contains
list=account_notification%2F
, where%2F
is a URL-encoded forward slash (/
).In the
unsubscribe_email
function inweb_views.py
, line 210, it's trying to access a field namednotify_on_account_notification/
which doesn't exist in theNotificationSetting
model.This exception occurs because the forward slash in
account_notification/
is being treated as part of the field name.
Claude immediately proposed this band-aid solution:
# Strip any trailing slashes from email_list to prevent field lookup errors
email_list = email_list.rstrip('/')
It seemed decent, but something bothered me. I thought the real issue might be elsewhere, so I asked Claude:
"This URL should be generated by our own code. Can you check if the root cause is with the code generating this
list=account_notification/
?" Upon further investigation, Claude found the real culprit:Now I found the source of the problem. Let's look at the code in
__init__.py
line 136-138 where the unsubscribe URL is created:...
The issue is right there. The
mailing_list
variable used in this URL is created at line 95:...
For account notifications, the value of
mailing_list
becomesaccount_notification/
with a trailing slash.
Claude then provided the proper fix:
# Strip any trailing slashes from mailing_list to prevent URL parsing issues
clean_mailing_list = mailing_list.rstrip('/')
unsub_url = syndicate.build_full_url_for_syndicate(
f'/unsubscribe_email/?unsub_token={user.unsub_token}&list={clean_mailing_list}',
user.syndicate_name)
ctx['unsub_url'] = unsub_url
headers = {
'List-Unsubscribe': f'<{unsub_url}>, <mailto:support@obico.io?subject=Unsubscribe_{clean_mailing_list}>'
}
🚨 Pro Tip: Always trace bugs back to their source; don't just patch the surface.
Example 2: The Case of the "Undeleted" Printer
Here's another fun one I faced—a deleted printer inexplicably returned from the grave whenever a print job finished. Here's my initial prompt to Claude:
I run into a mysterious issue in production: a deleted printer will be undeleted. I was able to reproduce it and found out that this happens when a print from the deleted printer finishes. I suspect this is caused by a bug in a code that is triggered at the time when a print finishes. help me figure out the bug.
The related server log is:
...
Claude responded confidently:
The bug is in the
unset_current_print
method of thePrinter
class, which is called when a print finishes.In the server logs, I found that when a print from a deleted printer finishes, the code was setting
deleted = NULL
in the printer record, effectively undeleting it. The issue is that theunset_current_print
method didn't check if the printer was already deleted before saving it....
The fix I implemented checks if the printer's
deleted
field is set before saving it. If the printer has been marked as deleted, the method returns early, skipping thesave()
call and subsequent operations. This prevents the deleted printer from being unintentionally restored when a print finishes.
Claude initially proposed this quick fix:
# Don't save and trigger printer events if this printer has been deleted
if self.deleted:
return
However, something felt off. I replied:
I don't think your fix works, because "self.deleted" must have been "null" and that was why "self.save()" caused the "deleted" field to be set to null. I suspect this is because "self" is a stale object with "delted" still being null
Claude quickly realized the mistake and revised the solution:
You're absolutely right. My initial fix wouldn't work properly because the
self
object could be stale, with itsdeleted
field still beingnull
even though the printer has been deleted in the database.The issue is that when we call
self.save()
, it overwrites all fields in the database with the current values in the object, which would include setting thedeleted
field back tonull
- effectively un-deleting the printer.I've improved the fix by adding
self.refresh_from_db()
before checking the deleted status. This ensures we're working with the most current database state of the printer, including its accurate deletion status.
Here's Claude's corrected fix:
# Correct fix: refresh from DB first
self.refresh_from_db()
if self.deleted:
return
😊 Pro Tip: Always double-check your object's state before hitting save.
Light-Hearted Best Practices for Working With Your Junior AI
So, my vibe coding assistant has some growing pains. No worries! Here are some friendly best practices I've found helpful for navigating these quirks:
- Always trace bugs to their source. Superficial patches mean future headaches.
- Refresh from the database. Keep your objects current before modifying them.
- Test first, fix second. Writing a test that reliably fails and then passes with your fix ensures real solutions.
Remember, your AI assistant is a teammate—enthusiastic but occasionally overconfident. Like a good senior dev, your oversight helps your digital junior dev avoid rookie mistakes.
Conclusion: Rookie Moves and Human Smarts
So there we have it—a humorous yet cautionary tale about today's vibe coding tools. While AI coding assistants are brilliant at handling many tasks, their occasional slip-ups remind us why human oversight remains essential.
As I've seen firsthand:
- Symptom-only fixes scream "junior dev!"
- Real debugging means going back to the root cause.
- AI can speed up your workflow, but you're still the brains behind the operation.
Have a hilarious or cringe-worthy AI coding fail to share? Drop your best "AI did what?!" moments in the comments! Let's laugh, learn, and commiserate together.