Guide
The nine Stripe decline codes that stop retries dead
Last updated 28 July 2026 · written by Bruce McGinley, who builds RecoverFlow
There are exactly nine decline codes where Stripe will keep a subscription's retry schedule running but will not actually attempt the charge until a new payment method exists on the customer.
They are incorrect_number, lost_card, pickup_card, stolen_card, revocation_of_authorization, revocation_of_all_authorizations, authentication_required, highest_risk_level and transaction_not_allowed.
If you see one of these, the retry is not the lever. Getting a new card on file is the only thing that changes the outcome.
On this page
The list
| Decline code | What it means and why waiting will not help |
|---|---|
incorrect_number | The card number itself is wrong. No amount of waiting fixes a typo. |
lost_card | The cardholder reported the card lost. The issuer will keep saying no. |
pickup_card | The issuer wants the physical card retained. Treat it as permanently dead. |
stolen_card | Reported stolen. Never tell the customer this is the reason. |
revocation_of_authorization | The customer told their bank to stop this specific merchant. |
revocation_of_all_authorizations | The customer told their bank to stop all recurring charges. |
authentication_required | The charge needs SCA. Only the cardholder can complete it. |
highest_risk_level | Stripe Radar blocked it. Retrying does not lower the risk score. |
transaction_not_allowed | The issuer does not permit this type of transaction on this card. |
That is the complete list as documented by Stripe. Every other decline code is one Stripe will keep attempting on schedule.
What actually happens when one of these fires
This is the part that confuses people looking at their own data. Stripe does not cancel the retry schedule when it sees one of these codes. The invoice stays open, the attempt counter keeps climbing, and the schedule keeps ticking. What changes is that Stripe stops sending the charge to the network, because it already knows the answer.
So an invoice can show several attempts against a stolen card without a single one of them ever having reached the issuer. If you are counting attempts as a measure of effort, you will overcount. If you are counting them as a measure of hope, you will overcount badly.
The practical consequence: your retry configuration has no effect on these invoices. Widening the retry window from two weeks to two months does not give them more chances. It gives them a longer wait before Stripe gives up.
What to do instead
All nine resolve the same way: a new payment method. What differs is how you should ask for it.
incorrect_numberis usually a typo during signup. Ask plainly, mention the card ending, and make the update link one click. These convert well because nothing is actually wrong with the customer's relationship to you.lost_card,pickup_cardandstolen_cardmean the customer almost certainly already has a replacement card in their wallet. They just have not told you. This is the highest value group to email, and the easiest to recover, because the fix costs them thirty seconds.revocation_of_authorizationandrevocation_of_all_authorizationsare different in kind. The customer went to their bank and told it to block you, or to block everything recurring. Treat the first as a churn signal and the second as a life event. Emailing is still fine. Emailing five times is not.authentication_requiredmeans the transaction needs Strong Customer Authentication and only the cardholder can complete it. Stripe can send a link that lets them authenticate. That link, not another retry, is the whole job.highest_risk_levelis Radar declining the charge, not the bank. Retrying does not lower a risk score. If you believe it is a false positive, the fix is in your Radar rules, not in your dunning.transaction_not_allowedusually means the card cannot do recurring, cross border, or this merchant category. A different card fixes it. The same card never will.
One thing never to put in the email
For lost_card, pickup_card, stolen_card and highest_risk_level, do not tell the customer the reason. Stripe's own guidance is that revealing these gives useful feedback to whoever is holding a card they should not have.
Write the generic version instead. Something like "we were not able to complete the payment on your card ending 4242" is honest, useful, and gives a card thief nothing. It is also, awkwardly, better copy: nobody wants to read the word "stolen" in an email from a company they pay.
How to find yours
You do not need any tooling to check this. In the Stripe Dashboard, filter invoices to unpaid, open a few, and look at the last payment attempt's decline code. Or pull it from the API: on a failed PaymentIntent, it is last_payment_error.decline_code.
Count what fraction of your unpaid invoices sit on these nine codes. That fraction is the share of your failed payments where retry configuration is irrelevant and only an email can help. In most subscription businesses it is a meaningful minority, but the only number that matters is yours, and we are not going to quote you an industry average we cannot stand behind.
There is a free decline code lookup on this site that covers 48 codes and marks these nine, if you would rather search than remember.
Questions people actually ask
Is insufficient_funds a hard decline?
No. insufficient_funds is not on Stripe's list of codes that block retry execution, and it is one of the better codes to retry, because the underlying condition genuinely changes when the customer gets paid. A lot of articles list it as a hard decline. They are wrong.
Does Stripe stop the retry schedule on these codes?
No. Stripe keeps the schedule and keeps incrementing the attempt count. It just does not send the charge to the card network until a new payment method is attached. The invoice looks like it is being retried when in practice nothing is being attempted.
Is expired_card on this list?
No, and that surprises people. expired_card is not one of the nine, so Stripe will genuinely retry it, even though an expired card does not become unexpired. Unless the issuer has pushed an updated card through the card account updater, those retries do nothing. It is an email problem wearing a retry problem's clothes.
Can I make Stripe retry these anyway?
You can turn Smart Retries off and write your own retry logic, but you cannot make the issuer approve a stolen card. The block exists because the answer is already known. Spending attempts on it only delays the point at which you ask the customer for a new card.
How many decline codes does Stripe have in total?
Stripe documents around 48 decline codes. Nine of them block retry execution. The rest are retryable to varying degrees of usefulness.
Where this came from
Checked against primary sources on 28 July 2026. If Stripe changes something and this page has not caught up, tell us and it gets fixed.
- Stripe: Smart Retries — the source for the 8 tries in 2 weeks default, the configurable window, and the nine code list.
- Stripe: Decline codes reference
- Stripe: Declines
If you would rather not build this yourself
RecoverFlow watches your Stripe account for failed subscription payments, stops retrying the ones that cannot succeed, and emails the customers whose card simply needs replacing. It charges 25% of what it actually recovers, with a $29 monthly floor, and nothing at all if it recovers nothing.
It is early. It is run by one person. If Stripe's own free retry settings are enough for you, use those instead, and there is a page on this site that says exactly when that is the right call.
See how the pricing works
Recover