Field Notes

How to fix a broken Replit app (and when to get help)

Sheet N-109 · By the Oracis engineering team · · 8 min read

Most Replit apps that reach us work. They work in the workspace, and the trouble starts at the public URL: the app will not publish, or it publishes and then loses uploads, forgets a setting, or breaks the moment a new feature ships. The cause is nearly always a difference between the workspace and the published app, which runs with its own secrets, its own database and its own file system. This guide is the order we work in, written so you can do most of it yourself, with a security checklist for a Replit app at the end.

Facts about Replit here come from Replit's own documentation (docs.replit.com) as of October 2026. Replit moves quickly, so check the current docs if a pane has been renamed.

First, stop the Agent from digging

Each prompt sent from a broken state adds changes on top of the problem. Replit Agent creates checkpoints as it works, each a snapshot of the project, and checkpoints are stored in Git. Roll back to the last checkpoint you know was good. The rollback can include the development database if you tick it; leave it unticked unless you mean to throw away development data too. A rollback never touches the production database.

Then turn on Plan mode with the toggle at the bottom right of the Agent's chat box. In Plan mode the Agent reads the project and answers questions but does not change any files. Replit's own advice is to start in Plan mode for anything involving several features or a significant change. Ask it to explain what went wrong, approve one fix, check it, then the next.

Find out where it fails

Two questions decide where to look: does the app work in Preview, and does it work once published?

  • Broken in Preview. Replit's guidance is to fix the app before publishing at all: if Preview does not show your app at a replit.dev address, publishing cannot help. Read the workspace console for the first error.
  • Fine in Preview, broken when published. Open the Publishing pane and its Logs tab. Look for a traceback, a missing package, a failed command, a variable that is not set, or a crash during start-up.
  • Fine for you, broken for one customer. That is usually data or permissions, not hosting: note exactly which account and which record, and reproduce it with a test account.

Paste the exact log line into the Agent. "The published app is broken" gives it nothing; a stack trace with a file name and line usually gives it the answer.

Keep a copy outside Replit

Open the Git pane, connect a GitHub repository in your own account, and push. Because checkpoints are Git commits, the history comes with it. Any developer can now read the app without your Replit login, and you have a copy that does not depend on any one workspace.

The problems we find most often

These are the causes behind most Replit apps we are asked to fix, roughly in order of how often they appear. The Replit page gives a short summary of each.

1. Production has different secrets

Replit's troubleshooting guide says secrets set in the workspace do not carry over to the published app. They have to be entered again in the Publishing pane, as production app secrets. Undefined values, failed API calls, a database that will not connect, and broken sign-in or payments that appear only after publishing are the symptoms it lists.

Keep a written list of every variable the app reads, with a value for each environment, and make the app refuse to start when one is missing, so the failure is a clear line in the logs rather than a confused customer:

// at the top of the server's entry file
const required = ["STRIPE_SECRET_KEY", "STRIPE_WEBHOOK_SECRET", "SESSION_SECRET"];
const missing = required.filter((name) => !process.env[name]);
if (missing.length) {
  console.error("Missing settings: " + missing.join(", "));
  process.exit(1);
}

Use your app's own variable names. A process that exits is restarted by the platform, so this shows up in the Logs tab as a repeated, readable error.

2. The server is listening in the wrong place

A published app is unreachable, or publishing fails at its last step, when the server listens only on localhost or 127.0.0.1. It has to listen on 0.0.0.0. If the project's .replit file declares ports, one of them must map to external port 80, with the local port matching the one your server uses:

# .replit
[[ports]]
localPort = 3000
externalPort = 80

Three related failures from the same guide: the home page must answer within five seconds or the health check times out, so move slow start-up work out of the first request; a program that runs once and exits is restarted again and again, so the app needs a long-running process such as a web server; and an app with API routes or sign-in callbacks published as a Static Deployment will fail at the public URL, because static hosting serves files only. Switch it to Autoscale.

3. Files saved to disk disappear

The file system of a published app is not persistent and resets every time you publish. Anything the app writes to disk, such as uploaded images or generated PDFs, is gone at the next release. Store files in App Storage, Replit's object storage, or another object store, and keep records in the database. Validate the type and size of every upload as you move it; Replit's own security checklist lists that too.

4. A schema change breaks production when you publish

Replit gives an app a development database and a separate production database, and publishing applies your development schema changes to production. A change that is harmless on test data can break live data: renaming a column, dropping one, or adding a required column with no default to a table that already has rows. The safe pattern is to split each breaking change across releases:

  1. Add the new column, allowing empty values, and publish.
  2. Change the code to write both old and new, fill in the new column for existing rows, and publish.
  3. Switch reads to the new column and publish.
  4. Only then remove the old column, in its own release.

Each step is safe on its own, so a problem at any step stays small and reversible.

5. Recovering lost production data

If a release has damaged production data, move quickly: production databases have point-in-time restore, with 7 days of history on Core and up to 28 days on Pro and Enterprise. Restoring the database does not change the code, and rolling back a checkpoint does not change the production database, so recovery is three steps in order: restore production to just before the bad release, roll the code back to the matching checkpoint, then publish. Write the procedure down before you need it, and practise it once on a copy.

6. Signed in, but allowed to see anything

Replit Auth tells your app who the user is. It does not decide which records that user may read or change; that is your app's code. Replit's security checklist says to verify permissions before every action and to authenticate every API endpoint. The common gap is a route that checks someone is logged in and then returns whatever ID was asked for. Scope every query to the signed-in user:

// Express-style; the query is illustrative, use your own ORM
app.get("/api/invoices/:id", requireUser, async (req, res) => {
  const invoice = await db.invoices.findFirst({
    where: { id: req.params.id, ownerId: req.user.id },
  });
  if (!invoice) return res.status(404).end();
  res.json(invoice);
});

Then test it the way an attacker would: sign in as one test user and request another user's IDs directly.

7. Stripe set up two ways at once

Replit offers two ways to take payments with Stripe: a connector, where the Agent sets up a Stripe sandbox and you connect your live account when publishing, and your own keys in Secrets with your own webhook endpoint. Replit's guide says to use one method per environment, because mixing them causes conflicts. Two more details from the same guide catch people out. Products and prices do not copy from the sandbox to your live account; you create them in live Stripe yourself. And the published app needs a live key, starting sk_live_ or rk_live_, in its production secrets.

With your own keys, register a separate live-mode webhook endpoint in Stripe at your published URL plus the webhook path, and put its signing secret in production secrets as STRIPE_WEBHOOK_SECRET. If signature checks fail, that secret not matching the endpoint is the usual reason. Before you share the app, make one low-cost real purchase with your own card.

A security checklist for a Replit app before real users

Replit publishes a security checklist covering the front end, the back end and everyday habits. This is our short version of it for an app the Agent built, with the Replit-specific items added:

  1. No API key or secret appears in front-end code or browser storage; every key is in Secrets, with production values set in the Publishing pane.
  2. Every API route checks who is calling, and every query is limited to records that user may touch.
  3. Signed in as user A, requesting user B's IDs returns nothing.
  4. Database queries use the ORM or parameterised queries, never text built from user input.
  5. Sign-in and other sensitive routes are rate limited.
  6. Session cookies are set HttpOnly, Secure and SameSite.
  7. Uploads go to App Storage, not the disk, with type and size checked.
  8. npm audit (or your language's equivalent) has been run and serious findings fixed.
  9. You know your production restore window, and the code and data rollback steps are written down.
  10. The code is pushed to a GitHub repository you own.

When to get help

Bring in an engineer when the same failure survives a rollback and a few one-change prompts; before a schema change to a table with real customer data; before you take payments; or when the logs show an error you cannot explain. None of this means leaving Replit or starting again. The code underneath is standard, and for many apps Replit is the right place to keep running.

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 Replit apps, or see every price.

Want this kind of engineering on your system?

Next sheet · N‑110 How to Fix a Broken Base44 App