"Vibe coding" — describing what you want in plain English and letting an AI assistant write and run the code, mostly without reading it line by line — went from a niche term to something recruiters ask about in interviews inside about a year. And it's genuinely useful. I use it every day on this site. But there's a specific failure mode that doesn't show up until you've shipped a few dozen AI-generated changes, and it's worth naming precisely instead of waving at "AI can be wrong sometimes."
Running is not the same claim as correct#
When an AI assistant writes a function, runs it, and shows you output that looks reasonable, three separate things have happened, and only one of them is actually verified:
- The code compiles/parses. Verified — the tool ran it.
- The code executes without throwing. Verified — you saw output.
- The code does what you actually meant. Not verified — nobody checked the logic against your intent, they checked that a plausible-looking result appeared.
The trust gap is the space between (2) and (3). It's widest exactly when the output looks right, because a wrong number that looks plausible gets far less scrutiny than a wrong number that looks obviously broken. A function that returns undefined gets caught immediately. A function that returns a number that's off by 8% because of an edge case in date math can sit in production for months.
⚠The specific pattern to watch for
If an AI assistant says something like "I've fixed the bug and verified the output" after running a script once and eyeballing the result, that is not verification — it's a single anecdotal data point being described with the confidence of a test suite. Ask what was actually checked, and against what expected value.
Where the gap actually bites#
In my own work, the trust gap shows up in the same few places every time:
- Boundary conditions the happy-path prompt never mentioned. Empty arrays, zero, negative numbers, timezone edges. If I didn't say "handle the empty case," the assistant usually didn't think about it either — it optimized for the example I gave it, not the full input space.
- Silent type coercion. JavaScript/TypeScript will happily let a string and a number interact in ways that produce a number-shaped result that's wrong.
tsc --noEmitcatches a lot of this, but not all of it — a value typedanyor coming from an external API response can carry a wrong assumption straight through. - Copy-pasted logic that almost matches an existing pattern. When an assistant generalizes from one existing function in your codebase, "almost matches" is exactly the kind of near-miss that's hardest to spot in review, because it reads as familiar.
What I actually do differently now#
The part I refuse to leave to memory, I automated. This site runs a pre-commit
hook and a CI pipeline that gate every change the same way regardless of who or
what wrote it: tsc --noEmit and ESLint on one job, then a content job running
a frontmatter linter, an MDX compile check, a broken-internal-link checker and
an image check. Separately, pnpm qa runs a static security audit plus
Playwright suites for responsive layout and accessibility. None of that is
clever — it is deliberately boring, mechanical checking that does not care
whether the diff looked confident.
What the tooling cannot do is judge intent, so that is the part I still do by hand: read the diff line by line and ask what input would break it. The two questions are different. A green pipeline says the code is valid; only reading it says the code is right.
Underneath both is one habit: I stopped treating "the assistant ran it and it worked" as equivalent to "I reviewed it." Those are different levels of confidence, and conflating them is exactly how a plausible-looking bug reaches production.
💡A cheap habit that pays for itself
Before accepting an AI-written fix, ask it directly: "what's the one input that would break this?" Forcing the model to generate its own adversarial case surfaces gaps a plain "does this look right?" review misses, and it costs one extra message.
This isn't an argument against vibe coding#
It's an argument for being precise about what part of the process is actually trustworthy. The code-generation speedup is real and I'm not giving it up. The verification step is a separate job that doesn't go away just because the first job got faster — if anything, it matters more, because more code is moving through review per hour than before, and each unreviewed assumption compounds with the next AI-generated change built on top of it.
Related reading if you want the other half of this: why I still write tests for AI-generated code goes into the specific testing habits that catch this gap in practice.
Adesh Shukla
Frontend developer with a design background. Building DevStash — a developer ecosystem covering automation, AI workflows, and modern frontend systems.