What an insufficient_funds decline means on a Stripe renewal
Updated November 1, 2026
A renewal that fails with insufficient_funds means the card didn't have enough funds or credit for this charge. Trying the same card later only works if that changes. Here's what Stripe does, and a calm note you can send.
What the code means
When a subscription renews by charging a saved card, the customer isn't in checkout. Stripe calls that off-session: it uses the payment method already on file, and the card issuer decides whether to approve it. Stripe lists insufficient funds among the most common reasons an issuer says no: the customer doesn't have enough funds or credit.
Stripe shows that as the decline code insufficient_funds: "The card has insufficient funds to complete the purchase." It appears on the failed payment in the Dashboard. In the API, decline_code on the PaymentIntent's last_payment_error gives the same reason, and outcome.reason on the charge uses decline codes too.
Stripe's listed next step is an alternative payment method. Retrying the same card is a different matter. You won't always see a code this specific. Issuers put most declines in generic_decline. When this one does appear, don't quote it back: issuers discuss the details only with the cardholder. Other renewal codes are in the decline code guide.
Why a retry can't fix the balance
Stripe Billing can retry a failed subscription or invoice payment. Smart Retries uses an AI model to pick the times. You choose how many attempts, over 1 week, 2 weeks, 3 weeks, 1 month, or 2 months. The recommended default is 8 tries within 2 weeks. A custom schedule, with Smart Retries turned off, allows up to three retries, each a set number of days after the previous one. Each failure is an invoice.payment_failed event, with attempt_count and next_payment_attempt on the invoice.
A retry charges the first saved method in this order: the subscription's default payment method, its default source, the customer's default payment method, then the customer's default source. That picks which card to run. It doesn't look for one with more money on it.
insufficient_funds is not a hard decline. Stripe won't automatically retry incorrect_number, lost_card, pickup_card, stolen_card, revocation_of_authorization, revocation_of_all_authorizations, authentication_required, highest_risk_level, or transaction_not_allowed. For those, retries stay scheduled but only run after a new payment method is added. This code isn't on that list, so a scheduled retry can still charge the same card. Stripe also skips retries when no payment method is on file, the card is India-issued, or a Connect account has been disconnected.
A retry only changes the timing. It can succeed if money has arrived, or if Stripe will now charge a different method. If the same card is still short, the issuer declines it again. After the final attempt, Stripe stops, and your settings cancel the subscription, mark it unpaid, leave it past due, or pause it when it's eligible. See the past_due guide. Stripe also recommends no more than eight retries: card networks limit repeat attempts, and extra tries can look like fraud.
Payday, the start of the month, and what Stripe times
Smart Retries does use the clock. Stripe says the model looks at time-dependent signals, including how many different devices have presented the payment method in recent hours, and that debit-card payments in certain countries might be slightly more successful at 12:01 AM local time. The docs don't say Smart Retries waits for a payday or the first of the month.
The dates still matter, because the code is about the balance at that moment. If your customers are paid on a salary date or near the start of the month, a retry before the money arrives fails the same way, and a retry after it has a chance. You can't see the balance, and the email shouldn't guess. On a custom schedule you choose the gaps, up to three. If you bill on the first, leave a gap so the next attempt falls after payday. With Smart Retries you don't pick the days, only the count and the window.
Check the advice code on the charge outcome before you assume another try is welcome. try_again_later means a retry is allowed. do_not_try_again means don't reuse this card for this charge. confirm_card_data means some card detail was wrong. An error can carry an advice code next to the decline code, and insufficient_funds doesn't tell you which one you received.
What Stripe's failed-payment emails cover
Turn on Send emails when card payments fail in Stripe's email settings. Stripe then emails the customer after each failed payment. The note says the recent subscription payment failed, and it links them to a place where they can update the payment method so a later attempt can succeed. The email uses your branding. The link can go to a Stripe-hosted page or to a page you host.
On the Stripe-hosted page, the customer can update the payment method for that subscription and pay outstanding invoices, if that applies. If they only update the method, Stripe uses it the next time a payment is scheduled. Stripe doesn't add that hosted link when the subscription is set to send the invoice manually.
That's the job the docs describe. They don't describe the email as naming insufficient_funds, explaining the balance, or suggesting a wait until payday, and it isn't a note you wrote. The hosted link stops working if the subscription becomes canceled, incomplete_expired, or unpaid, or the current renewal period ends. A reminder is most useful while the subscription is still past_due. Because Stripe sends one after each failure, a retry schedule can mean several emails about one invoice. Keep the retries, and pick one sender. If that's you, turn Stripe's failed-payment email off. More on the split is in Smart Retries vs dunning emails.
A message you can send
Don't name the code. It's private. Don't threaten to cancel, and don't invent a fee. Send one link, from an address you read, where they can update the card or try the payment again.
Hi Sam, this month's payment didn't go through. It happens. You can update your card or try the payment again here: [link]. If a later day works better, just reply and we'll sort it out. Thank you!
If you write again, keep that tone. Point the link at the method Stripe will actually retry. When the subscription has its own default payment method, updating only the customer's default leaves later attempts on the old card.
Where Calmretry fits
Calmretry works on top of your own Stripe account and doesn't replace Smart Retries. It notices failed subscription payments, including ones declined for insufficient funds, and sends a short sequence of gentle reminders from you, each with a secure link to update the card. Emails stop when the invoice is paid, voided, or the subscription is cancelled. It never touches funds or card data. If you use it, turn off Stripe's failed-payment email so your customer hears from you once.
See your own failed payments, for free
Calmretry reads your Stripe account with a restricted, read-only key and shows the failed subscription payments from the last 90 days: what was paid later, what is still open, and the decline reasons. It never touches funds or card data.
Sources
- Stripe Docs: Decline codes
- Stripe Docs: Card declines
- Stripe Docs: Automate payment retries
- Stripe Docs: Automate customer emails