The 9 Stripe decline codes that stop retries | RecoverFlow

Guide

The nine Stripe decline codes that stop retries dead

Last updated 28 July 2026 · written by Bruce McGinley, who builds RecoverFlow

Short answer

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.

The list

Decline codeWhat it means and why waiting will not help
incorrect_numberThe card number itself is wrong. No amount of waiting fixes a typo.
lost_cardThe cardholder reported the card lost. The issuer will keep saying no.
pickup_cardThe issuer wants the physical card retained. Treat it as permanently dead.
stolen_cardReported stolen. Never tell the customer this is the reason.
revocation_of_authorizationThe customer told their bank to stop this specific merchant.
revocation_of_all_authorizationsThe customer told their bank to stop all recurring charges.
authentication_requiredThe charge needs SCA. Only the cardholder can complete it.
highest_risk_levelStripe Radar blocked it. Retrying does not lower the risk score.
transaction_not_allowedThe 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.

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.

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