# Stripe: “Must provide source or customer.”

> Stripe says Must provide source or customer (parameter_missing) on a charge. The card token never reached the server. Fix it, then move to PaymentIntents.

Canonical: https://app369.com/fix/stripe-must-provide-source-or-customer/
Last updated: 2026-11-08

A server call to create a charge fails with parameter_missing: Must provide source or customer. The legacy Charges API needs something to charge, a card token or a customer with a saved card, and the request carried neither. Usually the token from the browser never made it into the request.

**Short answer**

Log the request body on the server: the token (tok_…) or saved card (card_…) is usually missing, misnamed or undefined. Send it as source, or pass customer for a saved card. Stripe has deprecated creating charges, so the lasting fix is to move this flow to the Payment Intents API or Checkout.

## **Why the charge has nothing to charge, and the fix**

1. 01 ### **The token never reached the server**
  > “One or more required values are missing.” [**Stripe, Error codes (parameter_missing)**](https://docs.stripe.com/error-codes) The form posted before Stripe.js returned the token, or the token was sent under a different field name, so source is undefined. Read the field your frontend actually sends, and fail early if it is empty. Also check the server parses the body: with a plain form post or JSON and no body parser, req.body is undefined.```
const { token } = req.body; // whatever the frontend sends
if (!token) return res.status(400).send('No card token');
await stripe.charges.create({ amount, currency: 'usd', source: token });
```
2. 02 ### **A customer without a saved card**
  > “The ID of an existing customer that will be charged in this request.” [**Stripe, Create a charge (customer)**](https://docs.stripe.com/api/charges/create) Passing customer alone works only if that customer has a card or other source saved to charge. If it doesn’t, attach one first, or pass the token as source. If you pass a saved card_… ID, pass the customer too.
3. 03 ### **The Charges API itself is on its way out**
  > “This method is deprecated and will be removed soon.” [**Stripe, Create a charge**](https://docs.stripe.com/api/charges/create) Code built on tokens and charges.create is the legacy flow, and it doesn’t handle 3D Secure authentication the way Payment Intents does. Move it to a PaymentIntent confirmed in the browser, or to Checkout, which creates the payment for you.
4. 04 ### **Migrating: no server-side charge step**
  > “In your existing integration, the final step is using tokenized payment information to create a charge on your server.” [**Stripe, Migrate to the Payment Intents API**](https://docs.stripe.com/payments/payment-intents/migration) With Payment Intents, the server creates the PaymentIntent and the browser confirms it with the card. The old step that posts a token to the server and creates a charge goes away.

Checked against the vendor’s docs on November 8, 2026: [Stripe docs: Error codes](https://docs.stripe.com/error-codes); [Stripe docs: Create a charge](https://docs.stripe.com/api/charges/create); [Stripe docs: Migrate to the Payment Intents API](https://docs.stripe.com/payments/payment-intents/migration).

## **Rather hand it over?**

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

- [$950**Stripe Billing Fix and Setup**Subscriptions, webhooks, customer portal and failed payments set up or fixed, tested in Stripe test mode.**See scope and start**](https://app369.com/fixed-price/stripe-billing-setup/)
- [from $450**App Fix Ticket**One reproducible bug in an existing mobile or web app, diagnosed and fixed.**See scope and start**](https://app369.com/fixed-price/flutter-firebase-bug-fix/)
- [from $450**AI-Built App Rescue**A 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. This applies to the first 10 Launch Checks bought after October 30, 2026.**See scope and start**](https://app369.com/fixed-price/ai-app-rescue/)

Related: [**Stripe “no default payment method” on renewal**](https://app369.com/fix/stripe-no-default-payment-method/) · [**Stripe “PaymentMethod was previously used”**](https://app369.com/fix/stripe-paymentmethod-previously-used-without-customer/) · [**Stripe “Received unknown parameter”**](https://app369.com/fix/stripe-received-unknown-parameter/) · [**Stripe customer portal not working**](https://app369.com/fix/stripe-customer-portal-not-working/)

Questions

## **More on this error**

<details>

<summary>**Do I have to migrate off charges.create now? **+</summary>

Stripe’s API reference marks creating charges as deprecated and says it will be removed soon. A fix that keeps it running buys time; plan the move to Payment Intents or Checkout.

</details>

<details>

<summary>**Why did this work in an old tutorial? **+</summary>

Many tutorials predate Payment Intents and post a card token from Stripe Checkout’s old popup or Elements to the server. The flow still exists, but it is deprecated and missing token handling is the usual bug.

</details>

<details>

<summary>**Can you fix it for me? **+</summary>

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. This applies to the first 10 Launch Checks bought after October 30, 2026.

</details>

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; Simon replies by email, usually within one business day.

[**Describe your problem **→](https://app369.com/contact/) [**All fixes**](https://app369.com/fix/)