Skip to content

Guides

Replit publish failed: how to find the real error

Niall Hackett ·

Step 1: Read the right log line

Open Publishing → Logs and scroll to the first ERROR or FAILED line. The last line is usually just the timeout that followed it.

Step 2: "A port configuration was specified but the required port was never opened"

Your server didn't start listening in time, which usually means something crashed or hung before listen().

  1. Bind to all interfaces and use the provided port:
    TypeScript
    const PORT = Number(process.env.PORT) || 5000;
    app.listen(PORT, "0.0.0.0", () => console.log("listening", PORT));
  2. Check that .replit maps the local port (e.g. 5000) to external port 80.
  3. Start listening first, then connect to the database and SDKs, with a log line per step.
  4. Add crash logging so the real error shows up:
    TypeScript
    process.on("unhandledRejection", e => console.error("unhandled", e));
    process.on("uncaughtException", e => console.error("uncaught", e));
  5. Make sure the server responds to GET / quickly. Health checks hit it.

Step 3: Production secrets are missing

Secrets in the workspace aren't automatically available to the published app. Open the Publishing settings and confirm every key your app reads (database URL, API keys, auth secrets) is set there too. A secret added recently in development is the usual culprit.

Step 4: "Failed to check for database diff: the endpoint has been disabled"

  1. Open the Database panel → Production and unpause the database if that option appears.
  2. If you added your own DATABASE_URL secret, it can conflict with the Replit-managed one. Rename it (don't delete it) and republish.
  3. Export a copy of your production data before retrying anything.

Step 5: Wrong deployment type

  • Static only serves files. If your app has a server, auth or a database, use Autoscale or Reserved VM.
  • "Could not find public directory" on Static means the output folder (often dist) is wrong.

Step 6: Stuck in a publish loop

Shut down the existing deployment from the Manage tab, then publish again. This resets the deployment record.

Step 7: Check the live app, not just the badge

"Published" means the deploy succeeded, not that the app works. Open the live URL in incognito with the console open, and test the pages that use the database.


Run a free ReplayWatch scan. Paste your live URL and ReplayWatch checks it for page load, security headers, secrets exposed in your HTML/JS, Supabase/Firebase data that is readable without login, broken links and assets, SEO tags, and whether your signup page is reachable. It does not log in or run your signup flow. → https://replaywatch.com/#scan