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
01
The token never reached the server
“One or more required values are missing.” Stripe, Error codes (parameter_missing)
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 });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)
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.
03
The Charges API itself is on its way out
“This method is deprecated and will be removed soon.” Stripe, Create a charge
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.
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
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 : Stripe docs: Error codes; Stripe docs: Create a charge; Stripe docs: Migrate to the Payment Intents API.
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. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: Stripe “no default payment method” on renewal · Stripe “PaymentMethod was previously used” · Stripe “Received unknown parameter” · Stripe customer portal not working