Everything works in the Replit workspace. The Agent has been building for a while, the preview pane looks right, you click around and it holds up. You hit Deploy, open the live URL, and something’s just gone — a blank page, a login that won’t complete, an API call that silently fails, a feature that worked ten minutes ago now throwing errors in the console.
If you’re searching “replit app works in preview but not deployed” or “replit app only works in replit,” this isn’t one bug — it’s a small set of distinct failure modes that all produce the same symptom (fine in the workspace, broken live). “Just redeploy” or “just ask the Agent to fix it” often doesn’t work, because you might be chasing the wrong one. Here’s how to tell which of the three you actually have.
Why this happens — 3 likely causes
All three share the same shape: something exists or is configured in your workspace that doesn’t automatically carry over to the deployed version, and the app quietly depended on it.
1. Environment variables and Secrets not carried into the deployment config. Replit’s Secrets pane and the deployment’s own environment variable settings are related but not automatically the same thing — depending on how the deployment was set up, a Secret you added to the workspace after the fact, or one added by the Agent mid-build, may never get copied into the deployment’s runtime environment. The workspace has the key; the deployed instance doesn’t. Anything reading that variable (an API key, a database URL, a feature flag) fails silently or throws on the missing value — and because the workspace still has it, preview keeps working while production doesn’t.
2. Auth callback URLs still pointing at the dev/workspace URL. Your Replit workspace runs on a *.replit.dev (or similar) URL during development, and a deployment gets its own separate URL. If you configured OAuth, magic-link auth, or any third-party callback (Stripe webhooks, an OAuth provider’s allowed redirect URI) while working in the dev workspace, that configuration is pointing at the dev URL — not the deployed one. The auth provider or webhook sender rejects or silently drops requests to a URL it doesn’t recognize as the registered target, which looks like “auth is broken” but is really “the redirect URL is stale.”
3. Dependencies or services that only exist inside Replit’s workspace sandbox. The Replit workspace is a full sandboxed environment — it can have packages installed ad hoc, background processes running, files written to a local path, or services (a local database, a cron-like script, a file the Agent created directly in the filesystem) that exist because something ran once in that session, not because they’re declared anywhere the deployment reads from. A deployment spins up a clean instance from what’s actually declared in your project — not a copy of your live workspace state. If the Agent (Agent 3, Agent 4, whichever autonomous run built the feature) installed something manually or wrote a file directly rather than declaring it as a dependency, it’s real in the workspace and absent in the deployment.
Diagnosing which one is yours
Don’t guess — check the deployment’s actual logs before trying a fix, since all three look identical from the outside (it “just doesn’t work”).
- Open your deployment’s logs (Replit’s deployment dashboard has a logs view separate from the workspace console) and reproduce the broken action. Look at what the server actually says at the moment of failure — a missing-env-var error, a rejected auth callback, or a “module not found” / “command not found” error each point somewhere different.
- A “module not found,” “command not found,” or crash-on-start error points to cause 3 (missing dependency/service). This is often visible immediately in the deploy logs, before you even reproduce the user-facing bug.
- An error mentioning an undefined value,
nullwhere a key should be, or a failed connection to an external service (database, API) points to cause 1 (missing environment variable). Check the specific variable name in the error against what’s actually set in the deployment’s own environment config — not the workspace Secrets pane. - A redirect that fails, an auth provider error page, or a webhook that never arrives points to cause 2 (stale callback URL). Open your auth provider’s or webhook sender’s dashboard and check exactly which URL is registered as the redirect/callback target, then compare it to your deployed URL.
The fix for each cause
If it’s cause 1 (env vars/Secrets not in deployment):
- Open your deployment’s settings (not the workspace Secrets pane) and list every environment variable it currently has.
- Compare that list against every Secret your app actually reads in code — grep for
process.env(or your language’s equivalent) if you’re not sure you’ve found them all. - Add any missing variable directly to the deployment’s environment config with the correct production value — don’t assume a value copies over just because it exists in the workspace.
- Redeploy after adding the variables — environment changes typically require a fresh deploy to take effect, they don’t apply to an already-running instance.
If it’s cause 2 (stale auth callback URL):
- Get your deployment’s actual live URL from the Replit deployment dashboard.
- Open your auth provider’s (or webhook sender’s) configuration and find every redirect/callback URL currently registered — OAuth redirect URI, webhook endpoint, allowed origins.
- Add the deployed URL as a registered callback/redirect target. If the provider allows multiple, keep the dev URL registered too so your workspace preview keeps working — don’t just replace one with the other.
- Save the provider-side config change, then test the full flow (not just that the login button renders) against the live deployed URL.
If it’s cause 3 (workspace-only dependency or service):
- Identify exactly what’s missing — the deploy log’s error (module name, command, connection target) usually names it directly.
- If it’s a package, add it properly to your project’s dependency file (
package.json,requirements.txt, etc.) rather than however it got installed in the workspace session — a manually-installed package in a live workspace doesn’t persist into a clean deployment build. - If it’s a service (a local database, a background script), check whether Replit’s deployment type you’re using supports it, or whether you need an external hosted version (a real database instance, a scheduled job configured through Replit’s deployment tools rather than a script left running in the workspace).
- Redeploy from a clean state if possible, and watch the build/deploy logs the whole way through — confirming the dependency installs and the service connects before you retest the user-facing feature.
How to verify it’s actually fixed in production — not just in the workspace
This is the step people skip, and it’s why the “fixed” bug reappears on the next deploy. The workspace passing tells you nothing here, because the workspace was never broken.
- Test on the actual deployed URL, in a fresh/incognito browser session — not the workspace preview pane, and not a browser tab with old cached state or an already-logged-in session.
- Reproduce the exact original failure end-to-end — if it was an auth flow, complete the full redirect round-trip; if it was an API call, trigger the actual feature, not just confirm the page loads.
- Check the deployment logs one more time during this test — a fix that removes the error from the logs is a much stronger signal than “the page looks fine,” since some failures fail silently in the UI.
- If you fixed a dependency/service issue, redeploy once more from scratch (not just refresh) to confirm the fix is in the declared project config and not an artifact of the previous deploy’s cache.
- If your app has both a workspace preview and a deployed production URL long-term, get in the habit of testing the deployed URL specifically after any change that touches env vars, auth config, or dependencies — not just after big feature changes. Divergence between “works in the sandbox” and “works deployed” is the recurring failure mode here, especially with the Agent building autonomously for long stretches where it’s easy not to notice the two have drifted apart until you actually deploy.