Short answer
Stripe keeps test and live data apart: an ID created with test keys doesn’t exist in live mode. Your database still holds customer IDs saved during testing, and the app now calls Stripe with live keys. Create a new live customer for each user whose saved ID came from testing, and make sure every server and environment uses keys from the same mode.
The usual causes, and the fix
01
Test IDs saved in your database
During testing your app saved cus_ IDs on user records. After the switch to live keys, those IDs don’t exist. Save the mode next to each ID; when it doesn’t match the key in use, create a new customer instead of reusing the old ID. The same goes for saved price, product and subscription IDs.
const customer = await stripe.customers.create({ email: user.email }); await saveUser(user.id, { stripeCustomerId: customer.id, stripeLivemode: customer.livemode, // true for live keys });02
Keys from different modes
One environment variable still holds a test key while another holds a live one: the server on sk_test_ and the browser on pk_live_, or a preview deploy and production sharing a database. Test keys start with sk_test_ and pk_test_, live keys with sk_live_ and pk_live_; restricted keys use rk_test_ and rk_live_. Stripe now calls the test side a sandbox, and its keys still start with test. Check each environment.
03
The customer lives on a connected account
With Stripe Connect, a customer created on a connected account only exists there. Requests about it need the Stripe-Account header with that account’s acct_ ID, or Stripe looks for it on your platform account and finds nothing.
await stripe.customers.retrieve(customerId, { stripeAccount: connectedAccountId, });04
A different account, sandbox or a deleted customer
Each Stripe account and each sandbox has its own keys and its own data. If the message doesn’t mention the other mode, check that the key comes from the account that created the customer, and that nobody deleted it in the Dashboard.
Checked against the vendor’s docs on : Stripe docs: API keys (sandbox versus live mode); Stripe docs: Error codes (resource_missing); Stripe docs: Make API calls for connected accounts.
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- $950Stripe Billing Fix and SetupSubscriptions, webhooks, customer portal and failed payments set up or fixed, tested in Stripe test mode.See scope and start
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way.See scope and start
Related: Stripe paid, account not upgraded · Stripe memberships not renewing