Skip to content

Stripe API errorNo such customer: ‘cus_…’; a similar object exists in test mode, but a live mode key was used to make this request

The customer ID belongs to the other mode, or to another Stripe account. It usually shows up the day you switch to live keys, and the same error appears the other way round when a live ID meets a test key. Here’s how to find which, or hand it over at a fixed price.

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

  1. 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
    });
  2. 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.

  3. 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,
    });
  4. 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.

Related: Stripe paid, account not upgraded · Stripe memberships not renewing

Questions

More on this error

Do my test products and prices carry over to live mode?

No. Objects in one mode aren’t available in the other, so products, prices, customers and webhooks have to exist in live mode too. Update every price ID your app has saved or hard-coded.

Should I delete the test customer IDs from my database?

Keep them only if you also save which mode they belong to. Otherwise clear them for real users before launch, so the app creates a live customer the first time each user pays.

Why does it work locally but not in production?

Your local environment and production almost certainly use different keys and often different databases. Compare the key prefixes in each environment and check which database production reads customer IDs from.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. 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.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; we reply by email, usually within one business day.