Short answer
If the decline_code is insufficient_funds, the customer’s bank said no. Nothing in your code is broken: show a clear message and let them pay with another card or method. If the error code is balance_insufficient, or a refund is stuck as pending, your own available Stripe balance is too low: wait for pending funds to become available (or top up if a refund is pending), then retry.
Which balance is short, and the fix
01
The customer’s card: decline_code insufficient_funds
“The card has insufficient funds to complete the purchase.” Stripe, Decline codes (insufficient_funds)
The issuer declined the charge for lack of funds or credit. Show a plain message and offer another payment method. Retrying the same card right away rarely helps; check outcome.advice_code on the Charge before any automatic retry.
02
Show the right message to the customer
“The customer needs to use an alternative payment method.” Stripe, Decline codes (insufficient_funds)
Stripe’s next step for this code is another payment method, so the checkout should keep the customer on the page with the error and a way to switch cards. For subscriptions, send them to update the card instead of retrying the same one.
03
Your Stripe balance: refunds stuck as pending
“Refunds use your available Stripe balance (not including pending amounts).” Stripe, Refunds
A refund draws on your available balance, not money that is still pending. If the available balance is too low, a card refund waits as pending until funds arrive; you can also top up the balance.
04
Your Stripe balance: transfers and payouts with balance_insufficient
“Stripe can’t complete this operation because the associated account doesn’t have enough available balance.” Stripe, Error codes (balance_insufficient)
With Connect, a transfer to a connected account or a payout fails when the available balance can’t cover it. Stripe doesn’t retry it for you: once funds are available, make the transfer again.
// check the available balance first const balance = await stripe.balance.retrieve(); console.log(balance.available); // [{ amount, currency }]
Checked against the vendor’s docs on : Stripe docs: Decline codes; Stripe docs: Card declines; Stripe docs: Error codes; Stripe docs: Refunds; Stripe docs: Connect account balances.
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 card declined: generic_decline · Stripe subscription stuck incomplete · Stripe Connect onboarding incomplete · Stripe “No such PaymentMethod”