Stripe decline codes, sorted by what fixes them
A failed subscription payment comes with a decline code. That code decides everything that follows: whether a retry can work, what the customer must do, and what you must not say to them.
The four families
Stripe lists dozens of card decline codes on its decline codes page. For recovering a subscription invoice they fall into four practical groups.
| Family | Typical codes | What recovers it |
|---|---|---|
| Money or limits | insufficient_funds, card_velocity_exceeded, withdrawal_count_limit_exceeded | A retry a few days later, or another card |
| Bank said no, no reason | generic_decline, do_not_honor, processing_error, issuer_not_available | A retry plus a reminder; the customer may need to call their bank |
| Needs a new card | expired_card, lost_card, stolen_card, pickup_card, incorrect_number, transaction_not_allowed | The customer adds another payment method |
| Needs authentication | authentication_required | The customer confirms the payment (3-D Secure) on the hosted invoice page |
The nine codes Stripe won't retry
Stripe's Smart Retries documentation lists the decline codes for which it cannot retry automatically: incorrect_number, lost_card, pickup_card, stolen_card, revocation_of_authorization, revocation_of_all_authorizations, authentication_required, highest_risk_level and transaction_not_allowed. For those, retries stay scheduled but only run once a new payment method is detected (source).
In other words: for these invoices, nothing happens until someone asks the customer for a new card. That email is the whole recovery.
What not to tell the customer
Stripe's guidance for lost_card, stolen_card, fraudulent and merchant_blacklist is explicit: don't reveal the specific reason, present it as a generic decline. A good dunning email says “your bank declined the card on file, the quickest fix is to use another card”, never “your card was reported stolen”.
Where to find the code on an invoice
- Open the invoice in the Stripe Dashboard and go to its payment attempts.
- Each failed attempt shows the decline code and the bank's message.
- Through the API, the last payment error of the invoice's PaymentIntent carries
decline_code.
SaveMyMRR's free scan reads this for every stuck invoice and groups them for you, in about a minute.
Questions
Is expired_card a hard decline?
It isn't in Stripe's list of codes it won't retry, but the old card can't be charged: the payment goes through once the customer's bank shares the new card details with Stripe, or the customer adds the new card. Asking for it is what recovers most of these.
What does do_not_honor mean?
The bank declined without giving a reason. Stripe's advice is that the customer contacts their card issuer. A later retry sometimes passes; a reminder email should ask for another card if it doesn't.