← Recoupt

Reference

Stripe failure codes — every code, every strategy

When a Stripe payment fails, the error object returns a decline_code indicating why. Each code maps to a specific recovery strategy: some warrant retry on a particular schedule, others require the customer to update their card, and a few mean the payment cannot be recovered. This reference groups every common code by what to do about it.

Source: Stripe’s declines documentation for the code list and meanings; Recoupt’s operational data for the retry schedules and dunning timing.

Category 1

Wait for payday

The customer’s account didn’t have the balance at the moment of billing. The right move is to wait for the next payroll deposit and retry — US payrolls run biweekly, so retries at 48h / 5 days / 10 days sweep the full window.

Code Meaning Recovery strategy
insufficient_funds Card has insufficient funds to complete the charge. Retry on the payroll cycle: 48h, 5 days, 10 days. US payrolls run biweekly, so this schedule sweeps the full payroll window.
withdrawal_count_limit_exceeded Customer exceeded the balance or withdrawal count limit on the card. Treat as insufficient_funds — wait for the next billing cycle. Alternative payment method may be required if limit persists.

Category 2

Transient — retry on the right schedule

Temporary failures that usually resolve within hours or days as a bank hold lifts or an issuer system recovers. The optimal retry schedule depends on whether the failure is processing-side (retry fast) or bank-side (retry over a few days).

Code Meaning Recovery strategy
card_declined Generic decline — usually a temporary bank hold or issuer-side risk check. Retry at 24h, 72h, 7 days. Most clear within the first 48 hours as the temporary hold releases.
generic_decline Same family as card_declined. Issuer rejected without giving Stripe a more specific reason. Same as card_declined: 24h, 72h, 7 days.
processing_error A transient error on the issuer or processor side. Often network or system-level, not card-specific. Retry fast: 4h, 24h, 72h. The underlying issue is usually transient and clears within hours.
try_again_later Stripe’s explicit "try later" signal — the issuer asked the merchant to retry without giving a specific reason. Retry with the card_declined schedule (24h, 72h, 7 days). Treat as a transient temporary failure.
issuer_not_available The card issuer’s authorization system was temporarily unreachable. Retry fast: 4h, 24h, 72h. Same shape as processing_error.
approve_with_id The issuer requires additional verification but the charge can sometimes succeed on retry. Retry with the card_declined schedule. If it persists, route to dunning so the customer can contact their bank.

Category 3

Customer action required — skip retries

No number of retries can succeed against an expired or compromised card — only the customer can update the card on file. The right move is to skip retries entirely and send the dunning email sequence immediately, so the customer has time to act before access lapses.

Code Meaning Recovery strategy
expired_card The card on file has expired. Skip retries entirely. Send dunning sequence immediately — only the customer can update the card.
incorrect_cvc The CVC code provided does not match the card. Skip retries. Send dunning so the customer can re-enter the CVC via the Stripe billing portal.
invalid_cvc CVC is not a valid format. Often paired with incorrect_cvc. Skip retries. Customer must re-enter card details via the billing portal.
authentication_required Card requires 3D Secure (3DS) authentication. Increasingly common under European PSD2 rules. Skip retries. Send dunning pointing at the billing portal where the customer can re-authenticate.
new_account_information_available The card on file has been replaced (number, expiry, or both). Issuer notified Stripe via account updater. Skip retries on the old card. Send dunning so the customer can add the new card. Stripe’s account updater service may auto-update if enrolled.
lost_card Card has been reported lost by the customer. Skip retries. Send dunning so the customer can add a replacement card.
stolen_card Card has been reported stolen. Same as lost_card: skip retries, send dunning for a new card.
pickup_card Issuer instructed merchant to confiscate the card. Often flagged for risk or compromise. Skip retries. Send dunning so the customer can add a different card.
card_not_supported Card cannot be used for this type of transaction (e.g. debit card on a credit-only merchant). Skip retries. Customer needs to use a different card. Send dunning.
currency_not_supported Card does not support the charge currency. Skip retries. Customer needs a different card or you need to change billing currency.

Category 4

Hard fail — recovery not feasible

Codes that indicate the customer or issuer has actively blocked recurring charges, or that the charge has been flagged as fraudulent. Retries and emails are not appropriate here — in some cases retrying actively makes the issue worse by triggering further flags.

Code Meaning Recovery strategy
fraudulent Stripe or the issuer flagged the charge as fraudulent. Do not retry, do not email. Charge will not succeed and pursuing it risks further flags.
merchant_blacklist Merchant is blocked from charging this card. Do not retry. Recovery requires resolving the underlying merchant-side issue.
security_violation Issuer rejected the charge for a security reason. Do not retry. Customer would need to contact their bank.
service_not_allowed Card cannot be used for this type of service. Do not retry. Customer needs a different card; route to dunning.
transaction_not_allowed Issuer prohibits this type of transaction. Do not retry. Send dunning so the customer can use a different card.
not_permitted Generic prohibition by issuer. Do not retry. Send dunning if customer action is possible.
restricted_card Card has been restricted by issuer. Do not retry. Send dunning for an alternative card.
revocation_of_authorization Customer revoked authorization for this specific merchant to charge recurring. Do not retry, do not email. The customer explicitly opted out of recurring charges.
revocation_of_all_authorizations Customer revoked all recurring authorizations on this card. Do not retry, do not email. Card is no longer available for recurring.
stop_payment_order Customer placed a stop-payment order on this charge. Do not retry. Customer explicitly blocked the charge; pursue support contact only.
pin_try_exceeded Customer exceeded PIN retry limit. Rarely relevant for online subscription charges. Do not retry. Send dunning if the customer needs to use a different payment method.

Category 5

Integration error — check your Stripe setup

These codes shouldn’t appear on tokenized recurring charges in production. If you see them, the issue is upstream — investigate your Stripe integration before retrying or emailing customers.

Code Meaning Recovery strategy
invalid_number Card number is not valid. Check your tokenization/Elements integration. Check Stripe integration. Should not appear on tokenized recurring charges in production.
invalid_account Account number is not valid. Check Stripe integration. Investigate if this appears on a previously-working subscription.
invalid_amount Charge amount is invalid (e.g. negative, zero, or above merchant limit). Check your billing logic. Recoupt does not modify the amount Stripe attempts.
invalid_expiry_month Expiry month is invalid. Check Stripe customer object. Should not appear on tokenized charges in production.
invalid_expiry_year Expiry year is invalid. Same as invalid_expiry_month.
duplicate_transaction A nearly identical transaction was submitted very recently. Check for duplicate retry logic. Stripe may have already captured the original charge.
testmode_decline A test card was used in live mode (or vice versa). Check Stripe environment configuration. Should never appear in production.
call_issuer Issuer requires the customer to call them before the charge can be approved. Skip retries. Send dunning explaining the customer needs to contact their bank.

How Recoupt applies this in practice

Recoupt reads the Stripe failure code on every failed payment and routes recovery accordingly. Payroll-family codes get the 48h / 5d / 10d schedule. Transient codes get card_declined’s 24h / 72h / 7d (or processing_error’s 4h / 24h / 72h for fast-clearing infra errors). Customer-action codes skip retries entirely and trigger the dunning sequence on day 0. Hard-fail codes mark the subscription for graceful cancellation without sending dunning emails that would only frustrate a customer who has explicitly opted out of recurring charges.

See the smart retry schedule per failure reason for the full timing logic, or the 3-step dunning sequence for what gets sent on customer-action codes.

Frequently asked questions about Stripe failure codes

What is a Stripe decline_code?

A Stripe decline_code is a short string returned in the error object of a failed card payment that indicates why the issuer or Stripe rejected the charge. Common values include insufficient_funds, expired_card, card_declined, authentication_required, and processing_error. Each code maps to a specific recovery strategy: some warrant retry on a specific schedule, others require the customer to update their card, and a few mean the payment cannot be recovered at all.

What is the most common reason a Stripe payment fails?

The three most common Stripe failure reasons for subscription billing are card_declined (a temporary bank hold or generic issuer decline), insufficient_funds (the customer’s account balance was below the charge amount at the moment of billing), and expired_card (the card on file expired and the customer has not updated it). Together these three account for the majority of recoverable failed subscription payments.

Should you retry an expired_card failure?

No. An expired_card failure can only be resolved by the customer updating their card on file — no number of retries against the expired card will succeed. The correct response is to skip retries entirely and send the dunning email sequence immediately, so the customer has time to update their card before the subscription lapses. Retrying an expired card wastes the retry budget and delays the email the customer needs to see.

How long does insufficient_funds usually take to resolve?

Insufficient_funds failures typically resolve when the customer’s next payroll deposit hits their account. US payrolls run biweekly, so a retry schedule of 48 hours, 5 days, and 10 days sweeps the full payroll window and catches most insufficient_funds failures within 14 days. A retry that fires earlier (at hours or one day after the failure) usually hits the same empty balance and burns the attempt with nothing changed.

What does authentication_required mean in Stripe?

authentication_required means the card issuer requires the customer to complete a 3D Secure (3DS) authentication challenge before the charge will be approved. This is increasingly common under European PSD2 regulations and on cards issued by banks that enforce 3DS for recurring charges. Retrying will not succeed — the customer must complete the authentication step, which means the recovery path is a dunning email pointing them at Stripe’s billing portal where they can re-authenticate.

The right strategy per code.

Recoupt reads every Stripe failure code and routes recovery accordingly — smart retries on the right schedule, dunning when the customer needs to act, graceful cancellation on hard fails. Free under $1K MRR.