Free reference
Stripe decline codes explained
Every card decline code Stripe returns, what it actually means, what to do about it, and the nine that Stripe will never successfully retry.
48 of 48 codes
The payment could not be authorized.
Next step: Attempt the payment again. If it keeps failing, the customer should contact their issuer.
The card was declined because the transaction requires authentication such as 3D Secure.
Next step: Trigger an authentication flow. The customer can pay once authenticated.
On a subscription this is awkward, because authentication needs the customer present. It usually means moving them to an on-session payment.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
The card does not support this type of purchase.
Next step: The customer should contact their issuer to enable the purchase type.
The customer has exceeded a balance, credit or transaction limit.
Next step: The customer should contact their issuer or use a different payment method.
The card does not support the specified currency.
Next step: The customer should check with their issuer about currency support.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
Common and frustratingly vague. Often temporary, so it is generally worth a spaced retry before giving up.
A transaction with identical amount and card details was submitted very recently.
Next step: Check whether a recent payment already succeeded before charging again.
The card has expired.
Next step: The customer needs to use a different card.
Not on Stripe’s hard decline list, so retries keep firing pointlessly. Treat this as an email trigger, not a retry.
Stripe suspects the payment is fraudulent.
Next step: Present as a generic decline. Do not disclose the reason.
The card was declined for an unknown reason, or was blocked by Radar.
Next step: The customer needs to contact their card issuer.
Stripe blocked the payment as highest risk.
Next step: Present as a generic decline. Do not disclose the reason.
The CVC number is incorrect.
Next step: The customer should retry with the correct CVC.
The card number is incorrect.
Next step: The customer should retry with the correct card number.
The PIN is incorrect. Card reader payments only.
Next step: The customer should retry with the correct PIN.
The postal code is incorrect.
Next step: The customer should retry with the correct postal code.
The card does not have sufficient funds to complete the purchase.
Next step: The customer should use an alternative payment method.
Among the most recoverable declines. Retry when funds are likely present, around paydays, rather than a few hours later.
The card or the account it is connected to is invalid.
Next step: The customer should contact their issuer to check the card works.
The payment amount is invalid or exceeds the amount permitted.
Next step: The customer should check with their issuer about amount limits.
The CVC number is incorrect.
Next step: The customer should retry with the correct CVC.
The expiry month is invalid.
Next step: The customer should retry with the correct expiry date.
The expiry year is invalid.
Next step: The customer should retry with the correct expiry date.
The card number is incorrect.
Next step: The customer should retry with the correct card number.
The PIN is incorrect.
Next step: The customer should retry with the correct PIN.
The card issuer could not be reached, so the payment could not be authorized.
Next step: Attempt again. If it persists the customer should contact their issuer.
Genuinely transient. A short backoff and retry recovers a good share of these.
The card was reported lost.
Next step: Present as a generic decline. Do not disclose the reason.
The payment matches a value on your Radar block list.
Next step: Present as a generic decline. Do not disclose the reason.
The card or account it is connected to is invalid.
Next step: The customer should contact their issuer.
Often means updated card details exist. Stripe’s Card Account Updater may pick these up automatically.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
The payment is not permitted.
Next step: The customer needs to contact their card issuer.
The card requires a PIN.
Next step: The customer should insert the card and enter a PIN.
The card requires a PIN.
Next step: Prompt for an online PIN if supported, otherwise the customer inserts the card and enters a PIN.
The card cannot be used, possibly because it was reported lost or stolen.
Next step: Present as a generic decline. The customer should contact their issuer.
The allowable number of PIN attempts was exceeded.
Next step: The customer should use a different card or payment method.
An error occurred while processing the card.
Next step: Attempt the payment again. If it persists, retry later.
Transient by definition. Short backoff then retry.
The issuer could not process the payment for an unknown reason.
Next step: Attempt the payment again. If it persists the customer should contact their issuer.
The card cannot be used, possibly because it was reported lost or stolen.
Next step: Present as a generic decline. The customer should contact their issuer.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
The customer has revoked all recurring authorizations. Retrying will not work, and continuing to try is a good way to attract a dispute.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
The customer has revoked permission for this recurring charge specifically. Treat it as a cancellation signal, not a retry candidate.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
The card was reported stolen.
Next step: Present as a generic decline. Do not disclose the reason.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
The customer has instructed their bank to stop this payment. Functionally a cancellation.
A Stripe test card number was used.
Next step: Use a real card.
If you see this in live mode, something in your integration is still pointing at test data.
The card was declined for an unknown reason.
Next step: The customer needs to contact their card issuer.
The card was declined for an unknown reason. Deprecated.
Next step: Attempt the payment again. If it persists the customer should contact their issuer.
The customer has exceeded a balance or credit limit.
Next step: The customer should use an alternative payment method.
The transaction requires authentication on the customer’s mobile device.
Next step: The customer needs to re-tap their device.
No decline code matches that. Try a shorter search, for example expired or cvc.
The nine codes Stripe will not retry
This is the part most people get wrong, so it is worth stating precisely. Stripe documents a specific set of hard decline codes. When one of these comes back, Stripe still schedules retries and still increments attempt_count, but the retry does not actually execute until a new payment method is attached.
- incorrect_number
- lost_card
- pickup_card
- stolen_card
- revocation_of_authorization
- revocation_of_all_authorizations
- authentication_required
- highest_risk_level
- transaction_not_allowed
In Stripe's own words: "For these failures, the scheduled retries continue but the payment only executes if you obtain a new payment method."
The practical consequence is that your retry count is not your recovery opportunity. If a chunk of your failures are these codes, no amount of retrying moves the number. Only getting a new card does.
The expired card trap
expired_card is not on Stripe's hard decline list. That means scheduled retries keep firing against a card that has expired.
They cannot succeed. An expired card needs a new number, not another attempt. So the retries burn through your schedule, increment the attempt count, and change nothing.
This is the clearest example of why decline codes matter more than retry volume. An expired card is an email problem, not a retry problem. The two things that actually fix it are prompting the customer to update their card, and Stripe's Card Account Updater refreshing it automatically where the issuer participates.
If you take one operational change from this page, make it this: route expired_card straight to a customer email rather than leaving it to the retry schedule.
Which declines are worth retrying
Outside the nine hard codes, the useful mental split is whether the reason is temporary.
- Genuinely worth retrying:
insufficient_funds,processing_error,issuer_not_available,try_again_later,reenter_transaction,approve_with_id. The card is fine, the moment was wrong. Timing is what recovers these, and payday proximity matters more than attempt count for insufficient funds. - Retryable in principle, but a data problem in practice:
incorrect_cvc,incorrect_zip,invalid_expiry_month,invalid_expiry_year. Retrying the same wrong details will fail identically. The customer has to correct something. - Not worth retrying: the nine hard codes above, plus
expired_cardfor the reason described.
A note on insufficient_funds. You will find sources that class this as a hard decline. It is not on Stripe's list of codes that block retries, and treating it as unrecoverable is a mistake. It is among the most recoverable declines there is, provided you retry when money is likely to be present rather than a few hours later.
Codes you should not explain to the customer
Stripe advises presenting certain declines generically rather than specifically. The reasoning is straightforward: if a card has been reported stolen, the person holding it may be the thief, and a precise error message is useful to them.
Present these as a plain "your card was declined, please try another payment method": fraudulent, lost_card, stolen_card, merchant_blacklist, pickup_card, restricted_card, highest_risk_level.
For benign codes such as expired_card, incorrect_cvc or incorrect_zip, being specific genuinely helps, so say what is wrong.
Finding your own decline codes
- In the Stripe dashboard, open Payments and filter to Failed.
- Open any failed payment. The decline code is on the payment detail page.
- Through the API, read
decline_codeon the charge outcome. It is more specific thanfailure_code, which is the broader category. - For subscriptions specifically, listen for the
invoice.payment_failedwebhook and read the decline code off the attached charge. Stripe also emitspayment_intent.payment_failedfor the same failure, and the two events differ in what they carry.
What you are looking for is the distribution. If most of your failures are insufficient_funds, better retry timing will move real money. If most are expired_card or the hard codes, retry tuning will do nothing and your effort belongs in customer emails instead.
Frequently asked questions
Which Stripe decline codes cannot be retried?
Nine: incorrect_number, lost_card, pickup_card, stolen_card, revocation_of_authorization, revocation_of_all_authorizations, authentication_required, highest_risk_level, and transaction_not_allowed. Stripe still schedules retries for these, but they only execute once a new payment method exists.
Does Stripe keep retrying an expired card?
Yes. expired_card is not on the hard decline list, so retries keep firing. They cannot succeed without a new card number, which is why an expired card should trigger an email rather than another attempt.
What is the difference between a hard and a soft decline?
A soft decline is temporary and the same charge may work later. A hard decline means the issuer has rejected the card in a way retrying will not fix. Stripe's own definition of a hard decline code is one where the issuing bank has rejected the transaction and you cannot retry it.
Where do I find decline codes in my Stripe dashboard?
Payments, filtered to Failed. Open any failed payment and the code is on the detail page. Via the API it is the decline_code field on the charge outcome.
Should I show the decline reason to my customer?
Not for fraud-related codes, which Stripe advises presenting as a generic decline. For benign ones such as an expired card or a wrong CVC, being specific helps them fix it.
See your own decline mix
RecoverFlow scans your last 90 days of Stripe invoices and breaks your failures down by decline reason, so you can see whether retry timing or customer emails is where your money actually is. Free, no card required.
Run the free 90 day scanCompiled from Stripe's published documentation on decline codes and revenue recovery as of 27 July 2026. Stripe occasionally adds or deprecates codes, so treat your own dashboard as the source of truth. Spotted something wrong? Email admin@recoverflow.org and it gets fixed.
Want to know what these are costing you? The retry waste calculator takes the counts from your last twenty failed invoices and works out how much of your failed revenue sits on codes no retry can ever collect. Runs in your browser.
Recover