cd /news/artificial-intelligence/vibe-coding-is-fine-vibe-debugging-i… · home topics artificial-intelligence article
[ARTICLE · art-112011] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

Vibe Coding Is Fine. Vibe Debugging Is What Kills You

A developer recounts how a duplicate-email bug caused by an in-memory Set in a multi-instance deployment took nine hours to find, with seven hours wasted watching an AI agent confidently fix unrelated issues. The engineer argues that 'vibe coding' is fine because the feedback loop is short, but 'vibe debugging' fails because the model has no ground truth and pattern-matches symptoms to common causes, leading to plausible but wrong fixes. The developer offers five rules to make AI debugging more effective, such as requiring a repro and capping diff size.

read6 min views1 publishedAug 26, 2026

We shipped a job that sent order confirmation emails. It deduped by keeping message IDs in an in-memory Set

. Clean code. An agent wrote it, I skimmed it, tests passed, staging was happy for two weeks.

Then traffic spiked, autoscaling added a second instance, and a few hundred customers got the same email twice. Two Set

s. Zero shared state. Obvious in hindsight, invisible in review.

Here's the part that actually cost me: finding it took nine hours, and roughly seven of those were spent watching an AI agent confidently fix things that were not the bug. Vibe coding didn't hurt me. Vibe debugging did.

Vibe coding is letting a model write code you accept without fully reading it. I do it every day and I'm not going to pretend otherwise.

It works because the feedback loop is short and the correctness check lives outside the model. Does the endpoint return 200? Does the page render? Does the CLI print the right thing? You don't need to understand the diff to evaluate it, because reality evaluates it for you in about four seconds.

Generation is also the thing language models are genuinely best at. Millions of examples of "function that takes X and returns Y" exist in training data. Your CRUD handler is not a novel artifact.

Because a bug is a claim about something that happened inside a process the model never watched. It gets a stack trace, a log line, and your grumpy one-sentence description. From that it does the only thing available: pattern-match your symptom against the most statistically common cause of that symptom.

That's right often enough to be dangerous. When it's wrong, it doesn't return an error. It returns a fix.

My duplicate-email bug looked exactly like a race condition, because it was a concurrency problem. So the agent proposed a mutex around the Set

. Textbook answer for a single process. Completely useless across two of them. The tests still passed. The duplicates kept going out. And now the code had a lock in it that would live there forever, quietly making every future reader assume the concurrency question had been handled.

Four moves, in this order, every time. You'll recognize all of them:

if (!x) return; The crash disappears. The bug relocates downstream, where it now looks like a different bug.Set

wasn't thread-safe." Stated as fact. Nothing was run.None of this is the model lying. It's what you get from a system optimized to produce a plausible patch, with no ground truth to check itself against. Give it no oracle and it will invent the feeling of one.

Because its own wrong theories become context. Turn 1 it says the issue is the lock. Turn 4 it's reading "the issue is the lock" as evidence in its own transcript. You've built a machine that cites itself.

I've watched an agent spend twelve turns defending a diagnosis I had already disproven in turn three, because my disproof was one line and its theory was six paragraphs.

Three strikes and you reset. Open a clean session and paste only facts: the repro steps, the actual observed values, what you ruled out and how. Not the conversation. The evidence.

Five rules. They cost real time up front and they've saved me entire days.

1. No repro, no agent. Spend the first hour making it fail on command. This is not preparation for the work, it is the work. Once you have a deterministic failing test, the agent's search has a terminal condition it can check by itself, and its hit rate goes up enormously. Before that, you're asking it to guess.

2. Make it explain before it edits. Ask for the causal chain with file:line

citations. Which line writes the bad value, which line reads it, what's between them. If it can't cite, it's guessing, and you just saved yourself a patch. One extra turn, kills most bad fixes.

3. Cap the diff. "Fix this in 10 lines or tell me you can't." Big diffs are where unfixed bugs hide. The constraint also forces a real diagnosis, because you can't shotgun a whole module in 10 lines.

4. Delete the fix and re-derive it. Once it's green, revert the patch and confirm the test goes red again. Embarrassing but true: a solid share of "fixes" I've accepted were placebo. The real change was a restart, a cleared cache, or an unrelated edit made three turns earlier in the same session.

5. Feed it observations, not adjectives. Don't say "it's flaky." Have the agent add instrumentation, run it yourself, and paste the actual values back in. It is an inference engine running on a bad prior until you hand it data. Accuracy is a function of what's in the context window, not how sternly you phrase the request.

A unique constraint on (order_id, template)

and an insert that catches the conflict. Three lines. The dedupe belonged in the database, which is the only thing in that system both instances agreed on.

The agent could have gotten there in one turn if I'd given it the right input. Instead of "emails are duplicating, here's the handler," the prompt that would have worked was: "this dedupe uses process-local memory; we run 2+ instances." That's not a prompting trick. That's me having done the diagnosis. The model was never going to discover the deploy topology by staring at the file.

Yes, and I'd argue it gets more worth it once you stop vibe debugging. Let the agent generate freely in places where reality checks the work fast: UI, scaffolding, glue, one-off scripts, anything with a visible output. Then move your attention from reading diffs to owning the feedback loop. Tests, repros, instrumentation, and a clear picture of what your system does at runtime.

The skill that appreciates here isn't prompt writing. It's being the person who can make a bug happen on demand. That's the one thing an agent still can't do for you, and it's the input that makes everything else it does actually work.

So: is vibe coding dangerous? Vibe coding is fine. It fails cheaply and visibly, because running the code tells you immediately whether it worked. Vibe debugging is what kills you, because an AI agent can't observe your runtime state and will answer a bug report with the most statistically plausible fix instead of the correct one. That fix often passes your tests, changes behavior, and hides the real cause under a lock or a null guard. Fix the loop, not the prompt: build a deterministic repro first, demand a cited causal chain before any edit, cap the diff size, revert-and-re-verify every fix, and start a fresh session after three failed attempts.

── more in #artificial-intelligence 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/vibe-coding-is-fine-…] indexed:0 read:6min 2026-08-26 ·