Why Is My AI-Built App Not Working? Error Codes Explained
"It's broken" is several different problems wearing the same complaint. Get the exact error, learn what its code means, then give your AI something it can act on.
Quick answer
When an AI-built app stops working, the cause is usually in one of a few places: data that was never saved to a real database, a permission rule hiding rows, a setting that exists in the preview but not on the live site, an outside service being turned away, or a problem at the provider, such as a paused database. The error code narrows it down: a code starting with 4 means the request was wrong or not allowed, and a code starting with 5 means the server failed. An empty list with no error is often a permission rule doing its job. Get the exact error first, then give it to your AI with the prompt below, and ask it to explain the cause before it changes any code.
Tools for this build
Custom Prompt Builder
Turns "it's broken" into a clear request with the steps, the symptom and the exact error.
PayFast Webhook Generator
If a payment notification is being refused, compare your code with a function that checks the sender's signature.
POPIA Compliance Checker
Once your data is saving properly, check where your users' personal information actually lives.
Start with the symptom, not a guess
Work through it in this order: get the exact error, match your symptom in the table below, read what the error code means, and only then give your AI the details. Each row links to the section or guide that explains the fix.
| Symptom | Likely cause | Where the fix is explained |
|---|---|---|
| Data disappears on refresh | No real database behind it: the data sits in the browser's memory or local storage, so it doesn't survive a refresh or a new visit | When your app needs a database |
| List is empty, no error | A permission rule (row-level security) quietly hiding the rows, not a broken connection | Empty results with no error, below |
| Breaks once it's live, fine in preview | A setting the preview had (a key, an address or a redirect rule) was never set on the live site | Preview and live are two different places, below, and environment variables not working after deploy |
| A number like 401, 403, 404, 429 or 500 | An HTTP status code: the server's short answer about what went wrong with one request | What the error codes mean, below |
| The browser console says "CORS" | The browser is blocking your app's call to another service on purpose | CORS error calling an API |
| Outside service is refused | The server side of your app only accepts signed-in users, which a payment gateway or other outside service can't be, or a signature check fails | When an outside service gets the error, below |
| Broke overnight, nothing changed | A paused free database, an expired key, a rate limit or an outage at the provider | When it worked yesterday, below |
| Works for you, breaks for real users | An untested edge case: unexpected input, a failed call to another service, or two people changing the same data at once | Why your vibe-coded app isn't production-ready yet |
| Works, but can't be found on Google | A visibility problem, not a broken feature | AI website not showing on Google |
Get the real error before you re-prompt
Open the live site, not the builder's preview, and open your browser's developer tools (press F12, or right-click the page and choose Inspect). Then repeat the exact action that fails. The Console tab shows error messages. The Network tab lists every request the page made; a failed one shows in red with a number in its Status column. That number is the status code the next section explains.
If the failing part runs on the server (a form that saves, a payment, an email), your builder or database usually also keeps logs of each server function. The message there is often more specific than anything the browser shows. Our guide to describing a bug to your AI covers where to find the error text and how to pass it on.
What the error codes mean, in plain English
Every time your app asks a server for something, the server answers with a three-digit status code. The web standard that defines them (RFC 9110) groups them by the first digit, and that first digit is the most useful thing to know. A code starting with 4 means the request itself was the problem: the standard says the client "seems to have erred". A code starting with 5 means the server failed or couldn't do it. So a 4xx usually points at something your app sent or wasn't allowed to do, and a 5xx points at the server side.
| Code | What it means | What to check in an AI-built app |
|---|---|---|
| 400 Bad Request | The server couldn't make sense of the request | A form sending a field in the wrong shape, a missing required value, or text where a number was expected |
| 401 Unauthorized | The request didn't prove who's asking: no valid sign-in or key came with it | The user isn't signed in yet, a sign-in has expired, or a key is missing on the live site |
| 403 Forbidden | The server understood the request and refuses it; if you're signed in, your sign-in isn't enough for this | A permission rule on the data, a role the user doesn't have, or a feature your plan with the provider doesn't include |
| 404 Not Found | Nothing was found at that address (or the server won't say whether anything is there) | A typo in a page or function name, a function renamed or never deployed, or a page that only exists in the preview |
| 429 Too Many Requests | Too many requests in a short time (a rate limit, defined in RFC 6585) | A loop calling a service over and over, a page re-fetching the same data on every change, or a busy period; wait, then retry more slowly |
| 500 Internal Server Error | Something unexpected went wrong on the server | The server function's own log, which has the real message the 500 hides |
| 502 Bad Gateway | A server in the middle got a bad answer from the server behind it | Usually the provider's side; retry, then check the provider's status page |
| 503 Service Unavailable | The server can't handle the request right now, usually because it's overloaded or under maintenance | The provider's status page, and whether your server function failed to start at all (its log will say) |
| 504 Gateway Timeout, or a timeout | A server waited too long for another one to answer | A slow outside service, or a function doing too much work in one go |
| "CORS" or "Failed to fetch", no code | The browser blocked the request or its answer, or no answer came back; this isn't a server code at all | A direct call from the page to another service that should go through a server function (see CORS error calling an API), a wrong address, or a server that's down |
Two more things worth knowing. First, 401 and 403 look alike but point different ways: a 401 is about who you are (sign-in), a 403 is about what you're allowed (permissions). Second, some platforms use their own numbers outside this list. When you see one, the platform's own documentation is the only reliable place to look it up; don't let your AI guess what it means.
Why does my app show nothing, with no error at all?
Often because a permission rule is working, not because anything is broken. Many databases behind AI-built apps use row-level security: rules that decide which rows each signed-in user may see. When a rule doesn't let the current user see a row, the database doesn't raise an error. It returns an empty list, as if the rows don't exist.
Supabase, a database many AI website builders connect to, puts it plainly in its troubleshooting documentation: when a query comes back empty, "usually this means you have RLS (row level security) enabled and no policy, or do not meet the policy." Saving is different. A new row the rules don't allow is refused with an error, but an edit or delete the rules don't allow can quietly change nothing, so check the row afterwards.
The usual causes, all fixable without touching the connection:
- No rules yet. Row-level security is on for the table, but nobody wrote a rule that allows reading, so everything is hidden.
- The rule checks the wrong thing. For example, it compares the user's ID with a column called
user_idwhen the table stores the owner inowner_id. - The app asks too early. The page loads the data before sign-in has finished, so the request arrives as a stranger and the rule rightly hides everything.
Rewriting the connection settings won't fix any of these. Ask your AI to show you the rules on the table in question and explain, in plain English, who each rule lets see what.
When an outside service gets the error
A payment gateway confirming a payment, or a messaging service passing on a message, calls your app's backend (the part that runs on a server, not in the visitor's browser) directly. It can't sign in as one of your users, so if that function only accepts requests from signed-in users, the call is refused with a 401 or 403 before your code even runs. The fix is to let that one function accept calls without your app's sign-in and have it check the sender another way, usually a signature the service adds to every call. Our guide to what a webhook is explains the idea, and webhook signature verification failed covers the signature check.
A related trap: typing a server function's address into your browser's address bar is not a fair test. Your browser sends a plain request with no sign-in and none of the data your app would send, so it can show an error even when the function works. Test it the way your app calls it, or with the test tool your builder or database provides.
When it worked yesterday and nothing changed
If no one touched the code, look outside it first:
- A paused database. Some providers pause free projects that see little use, and requests fail until you restore the project. Your provider's current plan terms say when that happens.
- An expired or changed key. A key for an outside service was replaced (rotated) or expired, and the next call fails with a 401 or 403.
- A rate limit. A burst of activity hit the provider's limit and you're getting 429s.
- An outage. The provider is having a bad day. Check its status page before you change anything.
Why the AI didn't catch these failures
An AI coding agent writes code from what the conversation showed it: your prompts, the data you tested with, the path you clicked through while the app looked finished. It can't allow for a live site it never saw, an input it was never shown, or two users acting at once when only one person ever tested it. That's the limit of building from one demonstrated run, not a defect in the tool. Our guide to why a vibe-coded app isn't production-ready yet goes deeper into why it happens.
Does my AI builder have a real database behind it?
Usually, yes. Many AI website builders, Lovable and Base44 among them, now come with a database, sign-in and server functions built in. If your data still disappears on refresh, the gap is that a table, a permission rule or the link between the screen and the database was never set up for that feature.
So ask your AI where that particular data is saved, and to show you the table. If the answer is "in the browser" or "in the app's memory", that's the cause.
Preview and live are two different places
The builder's preview runs somewhere the builder fully controls. Your live site, whether on the builder's own hosting or on another host, is a separate environment. It needs its own copy of every environment variable (a setting, such as a key or an address, that the app reads when it runs), build setting and redirect rule the preview relied on, and nothing carries across on its own. When a site works in preview but shows a blank screen or a failed request once it's live, compare those settings first, before you look for a new bug. Our guide to environment variables not working after deploy explains the mechanism.
The prompt to give your AI
Once you have the exact error, paste this into your AI website builder's chat or give it to your AI coding agent. Fill in the three lines at the top. It asks the AI to explain the cause before it changes anything, so a guess doesn't break working code elsewhere.
I'm not a coder. Something in this project isn't working.
What I did: [the exact steps, e.g. "signed in, opened Orders"]
What happened: [e.g. "the list is empty" or "a red error"]
The exact error: [paste the console message, the status code
from the Network tab, or the server log line]
Don't change any code yet. First, in plain English:
1. Explain what this error or status code means.
2. Tell me where it happens: in the browser, in a server
function, in the database, or at an outside service.
3. Give the most likely cause in this project, and how you
know. If it could be a permission rule (row-level security)
hiding data, check that and show me the rule.
4. Tell me whether it depends on a setting that exists in
preview but might be missing on the live site.
5. Describe the smallest change that would fix it, and what
else that change could affect.
If you're not sure, say so and tell me what to check next,
instead of guessing.What to check in the AI's answer
- It explained the error before offering a fix. If it jumped straight to rewriting code, ask it to go back to steps 1 to 3.
- The cause matches the code. A 401 answer should be about sign-in or a key; a 403 answer about permissions; a 5xx answer should point at the server log, not the page layout.
- It named a place. "Something in the backend" isn't enough. Ask which function, table or setting.
- For an empty list, it looked at the permission rules before blaming the connection.
- The fix is small. A fix that rewrites several files for one error is often a guess. Ask why each change is needed.
- It didn't move a secret key into the page. A key for a paid or private service belongs in a server function, never in code that runs in the browser. Our guide to why an API key can't go in frontend code explains why.
- It didn't ask you to switch security off. Turning off row-level security or removing a sign-in check to "make it work" swaps an error for an open door. Ask for the rule that allows only what you need.
Where to go next
- Why an app that works in a demo still breaks for real users: Why Your Vibe-Coded App Isn't Production-Ready Yet.
- Not sure if you even need a database yet: When Does Your App Actually Need a Real Database?.
- Other named errors, such as a blank screen after deploying or a failed webhook signature: the Errors & Troubleshooting hub.
Not affiliated with the platforms we write about
AI Build South Africa is an independent resource. We're not endorsed by, or an official partner of, Lovable, Base44 or Supabase. We do participate in affiliate and referral programmes with some providers named on this Site, including Base44. This guide explains general causes, not a complete audit of any specific project. See our Disclaimer for the full disclosure and our Terms of Service for the wider terms.
Frequently asked questions
What's the difference between a 401, a 403 and a 404?
A 401 means the request didn't prove who was asking: no valid sign-in or key came with it. A 403 means the server understood the request and refuses it; if you are signed in, your sign-in isn't enough, usually because of a permission rule. A 404 means nothing was found at that address, often a typo, a renamed page or a function that was never deployed.
What does a 403 Forbidden error mean on my app?
The server understood the request and refused it. In an AI-built app, that is usually a permission rule on the data, a role the signed-in user doesn't have, or a feature the provider doesn't include on your plan. Signing in again won't help if the account itself isn't allowed; the rule or the role needs changing.
What does a 500 error mean?
Something unexpected went wrong on the server while it handled the request. The 500 itself hides the real reason, so the useful message is in the server function's log, which your builder or database keeps. Give your AI that log line, not just the number.
What does "Failed to fetch" mean, and how do I fix it?
It means the browser never got a usable answer: the request was blocked, the address was wrong, or the server didn't respond. It isn't a server status code. Check the browser console for a CORS message next to it, confirm the address the app calls, and check whether the service is up.
Why does my app show no data when the table has data in it?
Often a permission rule, called row-level security, is hiding the rows from the user who is asking. The database returns an empty list rather than an error. Check that the table has a rule allowing the signed-in user to read it, and that the app only asks after sign-in has finished.
Should I just switch the permission rule off to make it work?
No. Turning off row-level security or a sign-in check makes the error go away by letting everyone see or change the data. Ask your AI for a rule that allows exactly what the feature needs, for example each user reading only their own rows, and to explain what it allows.
Why does it work in preview but not once it's live?
The preview and the live site are two separate environments. An environment variable, build setting or redirect rule that exists in one doesn't carry into the other on its own. Compare the settings on both before looking for a new bug in the code.
Should I just ask the AI to fix it again?
Only once you can give it the exact symptom and error text, not just "it's broken". A vague request tends to produce a guess that changes working code elsewhere. Give it the steps you took, what happened and the exact error, and ask it to explain the cause before it changes anything.
Related reading
- Understanding Your AI-Generated Project Structure: what your AI builder actually gave you, folder by folder, before working out what's missing.
- Environment Variables Not Working After Deploy: why a setting in the preview doesn't reach the live site.
- What Is a Database?: what a table, a row and a permission rule are, before you debug one.
- Blank Screen After Deploying? 4 Causes on Netlify or Any Host: when the app shows nothing at all instead of an error, the four causes behind a blank page after deploy.
- CORS Error Calling a Third-Party API: Causes & Fixes: the error that appears when your frontend calls another service directly, and why the fix is a backend function.