Guides / Rescue

Your vibe-coded app broke. Triage it like an engineer.

The failure loop is familiar: something breaks, you ask the AI to fix it, the fix breaks two other things, and an hour later the app is worse than when you started. The way out is not a better prompt. It is the same discipline engineers use on any unfamiliar codebase: rank the damage, pin the version, and change one thing at a time.

First, rank the damage. Not all broken is equal.

Before touching anything, place the problem in this order of severity, and deal with the highest one that applies:

  1. Data is exposed. Strangers can read or write things they should not. This outranks everything, including the app being down. Check with the signed-out probes in the RLS and Firebase guides, and if a key leaked, the response plan.
  2. Data is being corrupted. Writes are succeeding wrongly: duplicate charges, overwritten records. Take the write path offline if you can; wrong data compounds.
  3. The app is down. Painful, visible, and usually the least dangerous of the three. Downtime loses hours; the two above lose trust.
  4. A feature is wrong. Annoying, not urgent. This is the only tier where calm, unhurried fixing is the whole job.

Before you prompt again: pin the version.

The most expensive vibe-coding injury is self-inflicted: regenerating over a half-working app with no way back. Whatever state you are in, freeze it first:

git init          # if the project somehow is not a repo yet
git add -A
git commit -m "checkpoint: before attempting fix"
git branch known-good

From now on, every AI-assisted fix happens on a branch, gets tested, and is either committed or discarded whole. The known-good branch is the state you can always return to. This single habit converts "the AI destroyed my app" into "I threw away a branch".

Why the prompt-fix loop diverges Each "just fix it" prompt hands the model a bigger, more contradictory context, and each speculative rewrite touches code the model no longer fully sees. Fix one, break two is not bad luck; it is what unconstrained regeneration does to a codebase. The ladder below constrains it.

The debugging ladder.

  1. Reproduce it. Find the exact steps that trigger the failure, every time. A bug you cannot reproduce is a bug you cannot verify as fixed.
  2. Read the real error. The browser console and the server logs, not the AI's summary of them. The actual message, file, and line number are the highest-value tokens you own.
  3. Isolate before you fix. Narrow to the smallest failing piece: comment sections out, hit the API directly, binary-search the page. You are looking for the seam where working meets broken.
  4. Prompt narrow, with evidence. Give the AI the exact error, the relevant file, and the instruction to change only what is necessary. "Fix this null reference in submitOrder, do not modify other files" converges. "It is broken again, fix it" does not.
  5. Verify, then commit. Re-run the reproduction steps, click through the two features nearest the change, and commit with a message saying what changed. Small verified commits are what make the next bug cheap.
  6. Leave a tripwire. If you have any test setup at all, add one test that fails on this exact bug. It is the cheapest insurance against the AI reintroducing it next week.

The honest line: when a human is cheaper.

Call in a senior engineer when the bug touches money, sign-in, or data integrity; when the same symptom has survived three disciplined ladder attempts; or when fixing anything requires understanding everything, which is a sign the architecture, not a bug, is the problem. The economics are simpler than they feel: a focused day of senior debugging is routinely cheaper than a week of divergent prompting, and it usually ends with you understanding your own codebase better.

And if the app mostly works but launching it scares you, that is not a bug at all; that is the production-readiness checklist.

Questions

Questions founders ask.

Should I fix my vibe-coded app or rebuild it?

If the core flows work and users like the product, fix and harden; the working version embodies decisions worth keeping, and most breakage lives in a few identifiable seams. Rebuild only when the architecture itself blocks every change, which is rarer than frustration makes it feel. A review can settle the question in a day.

Why does every AI fix break something else?

Unconstrained regeneration: the model rewrites more than the bug required, guided by an increasingly contradictory conversation, and it cannot see the whole system it is editing. The countermeasures are boring and effective: version control, narrow evidence-rich prompts, one change at a time, verify before committing.

Is it safe to keep building on AI-generated code?

Yes, on three conditions: the code lives in version control with meaningful commits, changes are verified rather than assumed, and the security fundamentals from the twelve-point checklist have been run. Under that discipline AI-built code behaves like any other code: imperfect, improvable, and shippable.

What if I do not understand the code at all?

Start by asking the AI to explain, not to fix: a guided tour of the files, the data flow, and where each feature lives costs nothing and cannot break anything. Beyond that, an engineer can map the codebase for you in a session. Understanding is the durable fix; prompting without it is what created the loop.

When the loop will not close

Three failed attempts is the signal. Hand it to senior engineers.

We take broken and fragile AI-built apps, stabilise them, and hand back a working product with the fixes explained. If it only needs a few small changes, the review says exactly that, and you keep the list.