A Replit app works in preview but not when published because the published app is a separate copy with its own settings. Its secrets, its database, its run command, its port, and its deployment type are all set apart from the workspace. One of them is missing or different, and the publishing logs say which.
The preview only proves the code runs inside the workspace. Replit's own troubleshooting guide puts it in one line: a working Preview does not verify production configuration. This guide starts from what you can see, a failed publish or a live address that errors, and works out which setting is wrong. It's written for the founder who built the app with Replit Agent, and for the developer helping them. Every Replit behaviour described here comes from Replit's docs, checked in November 2026.
Why a Replit app works in preview but not when published
When you select Run in the workspace, the app starts with the workspace's secrets, the development database, and a replit.dev address. When you publish, Replit builds a fresh copy and runs it at a replit.appaddress. That copy shares your code and little else. Replit's docs list what to compare between the two: the build and run commands, production secrets, which database is selected, and the login configuration.
Six differences cover the causes Replit's docs list, and each has its own section below.
- Secrets. Secrets set in the workspace are not copied to the published app.
- Host and port. The published server must accept outside connections on the port Replit expects.
- The health check. Replit requests your homepage before it marks the app live.
- The run command. The published app needs a command that starts a server and keeps running.
- Deployment type. A Static deployment has no server behind it.
- The database and the disk. The published app reads a production database, and its file system resets on every publish.
If the app publishes and loads but the records are gone, that last one is your problem, and it has its own guide: a Replit app that lost data after publishing. The rest of this post is for an app that won't publish, or publishes and errors.
Find where the published Replit app fails: build, start, or requests
Replit's deployment troubleshooting guide says to identify the failing phase first: building, starting, or serving requests. Each phase has different causes, so this step decides which section you need.
- Rule out Replit.Open status.replit.com. If there's an incident on publishing, wait for it.
- Confirm the preview really works. Select Run and check the app loads at its
replit.devaddress. The docs are blunt that publishing won't repair a broken preview. - Open the logs. In the Publishing pane, open the Logs tab. For a failed publish, the docs say to find the deployment under Publishing, then History, and open its logs from the three-dot menu.
- Find the first error, not the last.Replit's docs say the first line marked
ERRORorFAILEDis usually the root cause, and the lines after it are usually knock-on effects. Copy that line before you change anything. - Keep the logs.The docs say to keep a failed deployment's logs before retrying, and not to republish an unchanged build. A second identical failure tells you nothing.
| What you see | Phase | Usual cause |
|---|---|---|
| Publish stops with a failed build | Build | Build command, a missing package, or a missing variable |
| "No run command configured" | Build | Run command not saved in the publishing settings |
| Build passes, publish fails at the final step | Start | Server on localhost, wrong port, or a homepage slower than five seconds |
| "Application failed to respond" | Start | App not listening on the port Replit expects |
| Internal Server Error, 500, or 502 | Requests | A crash in the app: missing secret, database, or a localhost URL |
| Blank page, or pages load but nothing saves | Requests | Static deployment chosen for an app that needs a server |
| Only login or payments fail | Requests | Redirect and webhook addresses still point at the preview |
| Slow first load, then fine | None | Autoscale starting from zero servers. Normal |
Replit publishing fails during the build
A build failure means Replit couldn't turn your code into something it can run. Replit's docs say most build failures come from missing dependencies, an incorrect run command, or a failed database migration.
Check the build and run commands
Open the Publishing pane and read both commands. The docs name the usual faults: typos, incorrect flags, the wrong entry file, and commands that only worked in the workspace. An app that needs a build step, such as a React front end, needs both a build command and a start command set there.
"No run command configured"
This one can appear even when a run command is set. Replit's fix is to disconnect the run command in the deployment settings, add it again, save, and publish again.
Variables the build needs
Some apps read a variable while building, such as an API address baked into the front end. If that variable exists only in the workspace, the build fails or produces a front end pointing nowhere. The docs say to check whether required environment variables are set for publishing.
A publish stuck on build or migration
Replit's docs give a reset: press Cmd+K on a Mac or Ctrl+K on Windows, search for Restart compute, run it, then select Publish. If it sticks again, that's a support ticket with the full build log attached.
Replit publish fails at the last step: host, port, health check
This failure is confusing because the build log is clean. The code built, the server started, and Replit still couldn't reach it. There are four causes, and one app can have more than one of them.
The server listens on localhost
Replit's docs say the server must listen on 0.0.0.0, and that listening only on localhost or 127.0.0.1does not work for published apps. Localhost means "only this machine may connect". Many frameworks default to it during development, which is why the preview can work while the published app can't be reached.
The port is hard-coded
"Application failed to respond" means, in Replit's words, that the app isn't listening on the port Replit expects. The docs' fix is to read the port from the PORT environment variable instead of a fixed number.
// Node (Express)
const PORT = process.env.PORT || 3000;
app.listen(PORT, "0.0.0.0");
# Python (Flask)
port = int(os.environ.get("PORT", 3000))
app.run(host="0.0.0.0", port=port)The .replit file exposes the wrong ports
Replit can detect your server's port by itself. But the docs say that once ports are defined in the .replit file, automatic detection is off, externalPort must be 80 for the publish to pass, and the server must listen on the matching localPort. Autoscale and Reserved VM deployments also support only one exposed port. The ports guide warns that if you expose more, or expose a single port on localhost, the published app will fail. Open .replit, check whether more than one port entry has built up, and leave one:
[[ports]]
localPort = 5000
externalPort = 80The homepage is too slow, or the program exits
Before marking the app live, Replit sends an HTTP request to it. The docs say that if the homepage takes more than five seconds to respond, the health check can time out and publishing fails at the final step. An app that loads a large file, calls an AI model, or runs a heavy query on the homepage fails here. Move that work behind a user action or cache it. Don't remove a login check to get past the health check; the docs warn against exactly that. The published app also has to be a program that keeps running. A script that does its job and exits gets restarted over and over.
Secrets missing from the published Replit app
Replit keeps two sets of secrets. Its docs say development secrets are only available in the editor, the published app reads from deployment secrets, and changing one store doesn't update the other. So an API key you gave Agent while building is not in the live app unless you also added it for publishing.
The docs list what a missing secret looks like: errors about undefined values, failed API calls, database connection failures, login errors, and payment failures. In the log it's often a line saying a variable is undefined, right before the crash.
- Open the Secrets tool in the workspace and write down every name. Names only, not values.
- Open the Publishing pane and compare its secrets against that list. Add what's missing.
- Use live values where the service has a test mode and a live mode. With a Stripe test key, the published app shows a working checkout and takes no real money.
- Select Publish. The docs say new values only go live when you publish again after updating the deployment secrets.
Never paste a secret's value into the Agent chat to "help it debug". If one has already been pasted there or into front-end code, replace it at the service that issued it.
Published Replit app returns 500, 502, or Internal Server Error
The app published, and the live address shows an error. Replit's docs say an Internal Server Error on a successfully published app comes from your app's code, not Replit's infrastructure, and that a 502 usually means the app process crashed. They also say a 500 or 502 is a symptom, not proof of a specific cause. So reproduce one failing request, note the time and the address, and read the runtime log around that minute.
Hard-coded localhost addresses
If the front end calls http://localhost:3000/api/…, it works in the workspace and fails for every visitor. The docs say to replace localhost and 127.0.0.1 references with relative addresses such as /api/orders, or ones built from environment variables. The same applies to an app that calls its own public address from the server: use a relative path.
The database isn't ready
Replit's docs say to confirm DATABASE_URL points at the production database, and to run pending migrations, the scripts that create or change tables, against production before publishing. A table that exists in development and not in production gives a 500 on the first page that reads it.
Reading restarts in the log
The docs explain two lines that worry people. SIGTERM means a graceful stop and is normal: Autoscale restarts regularly by design. Exit code 1 means the process crashed, and the cause is in the lines just before it.
Going back to the last working version
If real users are affected, open Publishing, then History, and redeploy the last version that worked. Check one thing first. The docs warn that redeploying code is not a database restore, and that an older version may not match the current database structure. If the broken release added or removed columns, the old code can fail in a new way.
Blank page or missing API: the wrong Replit deployment type
Replit has four deployment types, and picking the wrong one produces an app that publishes without errors and still doesn't work.
| Type | What it runs | What goes wrong |
|---|---|---|
| Autoscale | A web server that grows under load and drops to zero when idle. The default | First request after a quiet period takes a few seconds |
| Reserved VM | One dedicated server that never sleeps, at a fixed monthly cost | Costs the same with no traffic |
| Static | HTML, CSS, and JavaScript files only | No server, so no API routes, logins, or database calls |
| Scheduled | A command on a timer, then it stops | No web page and no public address |
Replit's docs say Static deployments are not compatible with apps created using Agent, because those need a back end. If the live site shows a blank page, or pages appear but forms and logins do nothing, check the type in the Publishing pane and change it to Autoscale. If the app really is static files, the other common cause the docs name is an incorrect public directory.
Slow first loads are a type question too. The docs call the delay on an Autoscale app's first request after scaling to zero a normal cold start. If the app has to stay connected, as a chat bot does, or runs memory-heavy background work, the docs point to a Reserved VM. A job that should run every night belongs in a Scheduled deployment, not in a timer inside a web app that may be asleep.
Login, payments, or CORS broken only on the published address
Sometimes the published app loads and one feature fails. That feature almost always depends on the app's address, which changed from replit.dev to replit.appor your own domain. For an app that publishes but breaks, Replit's docs list the settings to compare:
- Login callback or redirect URLs. Google sign-in and similar providers only send users back to addresses on their allowed list. Add the published address there.
- Payment webhook or redirect settings. Stripe sends payment events to an address you registered. If that is still the preview address, payments succeed and your app never hears about them.
- API allowlists and CORS.CORS is the browser rule that stops one site calling another without permission. If the front end and back end are the same app, the docs say to use relative addresses. If they're separate, allow the published front end's address on the back end, and only that.
- Files written to disk. The docs say the published file system resets on every publish, so uploads saved to a folder disappear. They belong in a database or storage service.
Test each of these on the published address, signed out, in a private window. That is how a new visitor meets the app.
Replit pre-publish checklist
Run this before every publish that matters. It takes ten minutes, and each line maps to a failure above.
Don't skip the last line. Publishing completing is not the same as the app working: Replit's own completion list ends with the main flow working at the public address and the logs showing no hidden startup errors. For the wider set of checks before real users arrive, from backups to who owns the accounts, use my vibe-coded app launch checklist.
When to get a developer for a Replit app that won't publish
Fix it yourself when the log names the problem: a missing secret, a port entry, the wrong deployment type. Those are settings, and the sections above cover them. Get a developer when the first error line points into code you can't read, when each Agent fix moves the failure somewhere new, or when the app publishes and real users hit errors you can't reproduce. If you're choosing someone, how to hire a developer to fix an AI-built app covers what to ask and what access to give.
For an app with users or payments, I start with a Launch-Ready Review: $900–1,500 and three to five days, ending in a written report with a fixed price for each fix. The fixes themselves, plus a proper deploy and monitoring, are a Production Sprint at $3,000–7,500. What sets the price inside those ranges is in the cost to fix a vibe-coded app.
Two projects show what the larger version looks like. The Chat Company came to me as a buggy demo the founder had generated with AI tools. I kept about 20% of the code, rewrote the rest, and launched in nine weeks for $20,000. It now serves 30+ businesses and handles 100K+ messages a day. On the social challenge app, an agency had left AI-generated code half-built, with security, login, and payment problems. I kept what was solid, rewrote the rest, and launched in eight weeks for $16,000. It now has 10,000 users.
If your published Replit app is failing and the log doesn't make sense, send me the first error lineand the app's link. I'll reply with which phase is failing and what I'd change.
Sources
- Troubleshoot publishing: logs, secrets, 0.0.0.0, ports, the five-second health check, Static deployments, Replit Docs
- Troubleshoot deployments: the build, startup, and serving phases; preview versus published, Replit Docs
- Deployment and publishing FAQ: run command, Internal Server Error, restarts, secrets, History, Replit Docs
- Networking and app errors: Application failed to respond, 502, 403, localhost URLs, migrations, Replit Docs
- Ports: localPort and externalPort, one exposed port for Autoscale and Reserved VM, Replit Docs
- Deployment types: Autoscale, Reserved VM, Static, and Scheduled, Replit Docs



