Field Notes
How to fix a broken Base44 app (and when to get help)
A Base44 app keeps almost everything inside the platform: the React front end, the data, sign-in, backend functions and hosting. That makes it fast to build, and it means most fixes also happen inside the platform, using settings and tools many founders have never opened. This guide is the order we work in when a Base44 app is misbehaving, written so you can do most of it yourself: get back to a working version, read the logs, understand the access rules that decide who sees what, fix the usual causes, and run a security checklist for Base44's stack before real users arrive.
Facts about Base44 here come from Base44's own documentation (docs.base44.com) as of October 2026. Base44 changes often, so check the current docs if a menu has moved.
First, get back to a version that worked
Prompting from a broken state builds on the problem. Base44's version history lets you restore an earlier version, or publish an older version directly while you carry on working on the draft, which is useful when the live app is broken and the fix is not ready.
Before the next change, switch the AI chat to Discuss mode, which proposes changes and makes none until you approve them. Ask it to explain the cause first. For errors that show up in the preview, Base44's "Resolve with AI" is free, so it is worth trying before spending credits on prompts.
Read the logs, and know what a blocked request looks like
Base44 records what your app does. In the editor, click Dashboard, then Logs. Filter the event type to Function Call to see each backend function run, and turn on "Errors only" to see failures; expanding a failed event shows the error message. The browser console (F12) shows the front end's side of the same failure.
One behaviour sends many founders the wrong way. When an access rule blocks a request, Base44 does not always report an error. A blocked list or filter returns an empty result, a blocked read of one record returns "not found" (404), and only blocked creates and updates fail loudly (403). Base44 designs it this way so a blocked request does not reveal whether the data exists. So if a page shows no data for one user and plenty for another, suspect the access rules before the code.
Get the code into GitHub
From the Builder plan, Base44 syncs code with a GitHub repository in both directions, on a branch that must be named main; on any plan you can export a ZIP. Connect early, because version history from before the connection cannot be recovered later. Two cautions before a developer works locally. Changes pushed to GitHub sync into Base44 but do not go live until someone clicks Publish. And in remote mode, local development writes go to the live app's production data, so a developer testing a feature can change real customer records. Agree who edits where, and give local work test data.
The problems we find most often
These are the causes behind most Base44 apps we look at, roughly in order of what they cost if missed. The Base44 page has a short version of each.
1. Access rules that are open, or not written at all
Base44 controls access to data at two levels. Row-level security (RLS) decides which records a user may create, read, update and delete. Field-level security (FLS) decides who may read or write a particular field. Each permission is true (everyone), false (no one) or a condition that compares the record with the signed-in user. Base44's own example limits reading and editing to the record's creator and deleting to admins:
"rls": {
"create": true,
"read": { "created_by": "{{user.email}}" },
"update": { "created_by": "{{user.email}}" },
"delete": { "user_condition": { "role": "admin" } }
}
Go through every entity and ask, for each of the four permissions, who should have it. A rule set to true to get a feature working is the most common finding. Use field-level rules for fields only some people should see or change, such as an internal note or a price. Any rule that refers to the user requires a signed-in caller, so anonymous visitors are refused outright. If you work in code, rule changes deploy with the CLI's entities push or a full deploy.
Then prove the rules: sign in as one test user and try to list, read, change and delete another test user's records.
2. Backend functions that skip the rules
Inside a backend function, base44.asServiceRole bypasses both row-level and field-level security completely. Base44 says plainly that the function is then responsible for any access checks it needs. Every deployed function also has its own web address, at /functions/<name> on your app's domain. So a function that uses the service role and takes a record ID from the request can, unless it checks, hand any record to anyone who can call it.
When a function is called from your app, the user's sign-in travels with the call. Check it before doing anything else, and check that this user may touch the record:
import { createClientFromRequest } from "npm:@base44/sdk";
export default async function (req: Request): Promise<Response> {
const base44 = createClientFromRequest(req);
const user = await base44.auth.me();
if (!user) return Response.json({ error: "Unauthorized" }, { status: 401 });
// Check this user may read or change the record before touching it.
// ...
}
A function called by an outside service, such as a webhook, has no signed-in user, and Base44's documentation says to use the service role for its work. That makes verifying the caller, for example a payment provider's signature, the function's first job.
3. Keys in the React code
Backend functions read secrets on the server with secrets.get() from base44:runtime, called inside the handler rather than at the top of the file. A key written into the React code instead is sent to every visitor. Create a new key with the provider, revoke the old one, store the new one as a secret, and move the call into a backend function.
4. The wrong people can open the app
Base44 apps are Public (anyone on the internet, no sign-in required), Workspace (everyone in your Base44 workspace, signed in) or Private (only invited people, signed in; a paid plan). An internal tool left Public is open to the world. Check the App Users list too: collaborators you add to the editor are given the Admin role in the live app by default, which may be more than they need once the app holds real data.
5. Payments that only work in one place
Base44's Stripe checkout runs only on the published app, never in the editor preview, so testing in the editor proves nothing. Test on the published app, with the success and cancel URLs pointing at your real domain; wrong return URLs are a common cause of a blank page after paying. If Base44 created a Stripe sandbox for you, claim it within 60 days so the account is in your name. Then test a renewal and a cancellation as well as a first purchase, and check that access follows each one.
6. A custom domain that breaks sign-in
Base44 handles the login and password-reset pages itself. Redirect rules added with a custom domain must leave those paths alone, or sign-in and password resets fail on the real domain while working on the base44.app address. After any domain change, test sign-up, sign-in and password reset on the custom domain from a private window.
7. No way back for the data
Restoring a version brings back code, not deleted records. Use Base44's Data Backup and Restore if your plan includes it, and export your data regularly in any case, so a bad prompt or a mistaken bulk edit is recoverable. If you are weighing a move off Base44 altogether, read what leaving involves on our Base44 page first: the front end moves easily, the back end does not.
A security checklist for a Base44 app before real users
Base44's security scan checks row-level security, hardcoded secrets, backend functions, npm dependencies and the code itself. Run it, fix every finding, then work through this list:
- Every entity has row-level rules for create, read, update and delete, and none is
trueunless the data really is public. - Sensitive fields have field-level rules.
- Signed in as user A, you cannot list, read, change or delete user B's records.
- Every backend function that uses
asServiceRolechecks the caller and the record itself; webhook functions verify the sender's signature first. - No API key is in the React code; every secret is read with
secrets.get()in a backend function. - The app's visibility is right for its audience, and only people who need it have the Admin role.
- Payments are tested on the published app: purchase, renewal and cancellation, with return URLs on your real domain and the Stripe account claimed.
- Custom-domain redirects exclude the login and password-reset paths.
- The code is in a GitHub repository on
main, and local development uses test data, not production. - Data is backed up or exported, and someone checks the Logs page for function errors after launch.
When to get help
Bring in an engineer when a problem survives a restore and a few careful prompts in Discuss mode; before you take payments or store personal data; when the security scan reports something you cannot explain; or when you need something the platform does not do. None of these mean starting again, and most fixes keep the app on Base44.
That is the work we do. A free 20-minute call tells you what we expect to find. The Quick Security Check ($495, in 48 hours) tests your published app from the outside for the problems above and tells you in writing what is exposed. How we fix Base44 apps, or see every price.