Skip to main content
20% off 3 months · code LAUNCH20 · until 31 October

Why does Stripe work in test mode but not on my live site?

Updated 1 October 2026 · by Nordva, who make Nordva Launch

The short answer

Stripe keeps test and live mode apart: each has its own keys, its own products and prices, and its own webhook endpoints. A checkout that works in the sandbox and fails live almost always still uses a test key, a test price id, or a webhook endpoint and signing secret that only exist in test mode. Check the keys first, then the price ids, then the webhooks.

The error you see, and where to look

What you seeUsually meansSection
”No such price”, often with “a similar object exists in test mode, but a live mode key was used to make this request”A test price id (or customer, product) sent with a live key2
Checkout opens but fails, or the browser and server disagree about modeOne test key and one live key1
”No signatures found matching the expected signature for payload” on the live siteThe test endpoint’s signing secret, or a request body changed before the check3
People pay, but their account never unlocksNo live webhook endpoint, or it isn’t subscribed to the event3
After paying, people land on localhost or a preview addressThe success and cancel URLs still point at your test setup4

1. The keys

Stripe’s docs are explicit that every request runs either in a sandbox or in live mode, and that each mode has its own set of API keys. Test keys start with pk_test_, sk_test_ or rk_test_; live keys with pk_live_, sk_live_ or rk_live_ (Stripe: API keys).

Check both halves:

  • The browser uses the publishable key (pk_live_… on the live site).
  • The server uses the secret or restricted key (sk_live_… or rk_live_…).

A live publishable key with a test secret key, or the reverse, fails in confusing ways. Look at the environment variables on your host, not in your local .env file: they’re different places, and hosts often keep separate values for preview and production.

2. The products and prices

Objects in one mode can’t be used in the other. Stripe’s own example: a sandbox product can’t be part of a live payment. So a price id you copied while testing (price_…) doesn’t exist in live mode, and the checkout fails with a “no such price” error.

Create the products and prices again in live mode, and put the live price ids in your production settings. Using a lookup key instead of a raw id makes this easier: the same name can point at the test price in the sandbox and the live price in production.

3. The webhooks

Webhook endpoints are set up per mode too, and each endpoint has its own signing secret, separate from your API keys. If your app fulfils orders when a webhook arrives (unlocks the account, sends the receipt), a missing live endpoint means people pay and get nothing.

In live mode, add the endpoint with your production URL, subscribe it to the same events as in test mode, and copy its signing secret into your production environment variables. The test endpoint’s secret won’t verify live events.

If the secret is right and verification still fails, check what reaches your handler. Stripe’s docs say the payload must be the request body exactly as Stripe sent it: a framework or middleware that parses the JSON first changes it, and the signature no longer matches (Stripe: resolve webhook signature verification errors).

4. Everything else in the go-live list

  • The production URL for redirects after checkout (success and cancel pages) points at your real domain, not localhost or a preview address.
  • Your site’s host has been redeployed since you changed the environment variables. Many hosts only read them at build or start time.
  • Stripe’s go-live checklist has nothing left open for your account.

How to test it safely

Make one real payment yourself with a real card, at your lowest price, then refund it from the Stripe Dashboard. It’s the only test that proves the live path end to end, and it takes two minutes.

With Nordva Launch

Once live payments work, connect Stripe to Launch with a restricted key (rk_live_…, read-only, on every plan). Launch never writes to your account; it reads customers and subscriptions to show where each paying customer first came from.

When Launch is the wrong tool

Launch doesn't process payments or fix a checkout; it only reads your Stripe account, read-only, to show where paying customers came from. This page is for getting the checkout itself working.

Also asked as
  • Stripe checkout works locally but not in production
  • Stripe webhook not working in live mode
  • No such price error in Stripe live mode
  • a similar object exists in test mode, but a live mode key was used
  • No signatures found matching the expected signature for payload
Read next
Start free Free plan, no time limit · No card