Subscription payment decline codes guide for Stripe
Subscription Payment Decline Codes: What They Mean and How to Recover Each One
TL;DR: When a subscription payment fails, your processor returns a decline code that tells you why. The problem: codes are inconsistent across networks and processors, and the most common one β "Do Not Honor" β tells you almost nothing. This guide maps every common decline code to a specific recovery strategy, so you can stop treating all failures the same and start recovering more of each type.
Subscription Payment Decline Codes: What They Mean and How to Recover Each One
How Decline Codes Work: The Anatomy of a Failed Payment
When a customer's payment is attempted, the request flows through a chain: your payment processor (e.g., Stripe) β the card network (Visa, Mastercard) β the issuing bank. The issuing bank makes the approve/decline decision and returns a response code that travels back up the chain.
What you see in your Stripe dashboard is Stripe's interpretation of the bank's response β which is often more descriptive than the raw network code, but still imperfect.
The Three-Layer Code Problem
Issuing bank
Raw response code (DE 39)
05
You don't see this directly
Card network
Standardized network code
05 β Do Not Honor
Available via Stripe API
Payment processor (Stripe)
Stripe-specific decline code
generic_decline
What appears in your dashboard
This layering creates a translation problem. The bank's raw code gets interpreted by the network, then re-interpreted by Stripe. Nuance is lost at each step. A single Stripe code like generic_decline can represent a dozen different underlying bank decisions.
Soft Declines vs. Hard Declines: The Critical Distinction
This is the single most important concept in payment recovery. Every decline falls into one of two categories, and your response to each should be completely different.
Soft vs. Hard Decline Comparison
Nature
Temporary β may resolve on its own
Permanent β won't resolve without action
% of all subscription failures
60β70%
30β40%
Can be recovered with retries?
Yes β often without customer knowing
No β requires customer to update payment
Examples
Insufficient funds, processing error, issuer unavailable
Expired card, invalid number, stolen card, account closed
Optimal response
Silent retry with optimized timing
Dunning email with card update link
Recovery potential
High (70β90% with smart timing)
Medium (40β60% with good dunning)
Danger of retrying
Low (within network limits)
Wastes retries and risks network fines
The golden rule: Exhaust smart retries on soft declines before contacting the customer. Send dunning communications immediately for hard declines.
Complete Decline Code Reference: Every Code, Every Recovery Strategy
Soft Declines β High Recovery Potential (Retry First)
51
insufficient_funds
Customer doesn't have enough money
30β40%
Retry around paydays (1st, 15th of month), morning hours in customer's timezone. Don't retry same day.
70β85% with optimized timing
05
generic_decline / do_not_honor
Bank refused β no specific reason given
15β25%
ML-optimized retries at varied times. May resolve on its own. This is the "black box" code.
40β60% depending on underlying cause
91
issuer_not_available
Bank systems temporarily down
3β5%
Retry within 4β24 hours. Almost always succeeds on next attempt.
90%+
06
processing_error
Generic processing failure
3β5%
Retry within 24β48 hours with different timing window.
80β90%
65
card_velocity_exceeded
Too many transactions in short period
1β3%
Wait 24β48 hours, then retry. Card's daily limit has been hit.
70β80%
61
withdrawal_amount_exceeds_limit
Transaction exceeds card's transaction limit
1β2%
Retry after 24 hours. If recurring, consider splitting into smaller amounts.
60β75%
N/A
try_again_later
Temporary issuer issue
2β4%
Retry within 4β12 hours.
85β95%
Hard Declines β Customer Action Required (Dunning Immediately)
54
expired_card
Card past its expiration date
10β15%
First check if Card Account Updater / Network Tokens can auto-replace. If not, send dunning email with one-click card update link.
60β80% (with CAU), 40β55% (email only)
14
invalid_number
Card number doesn't exist or is wrong
2β3%
Dunning email requesting customer re-enter card details.
35β50%
43
stolen_card
Card reported stolen
1β2%
Do NOT retry. Send gentle notification asking for alternative payment method.
30β40%
41
lost_card
Card reported lost
1β2%
Similar to stolen β Network Tokens may auto-update. Otherwise dunning email.
40β55% (with tokens), 30β40% (without)
04
pickup_card
Bank wants the card seized
<1%
Do not retry. Contact customer for new payment method.
20β30%
N/A
card_declined (with do_not_try_again advice)
Terminal decline β bank says stop
2β3%
Do not retry. Immediate dunning with card update form.
30β45%
Authentication Declines β Requires Customer Interaction
N/A
authentication_required
3D Secure / SCA challenge needed
5β10%
Send email with payment link that triggers authentication flow. In-app notification for active users.
50β65%
N/A
3ds_required
European SCA mandate
Region-dependent
Redirect customer to complete 3DS verification. Cannot be solved with silent retries.
55β70% with good UX
Fraud-Related Declines β Handle with Care
N/A
fraudulent
Stripe Radar or bank flagged as fraud
3β5%
If Stripe blocked: review in Dashboard, add to allowlist if legitimate. If bank-flagged: customer must call bank.
25β40%
59
suspected_fraud
Bank suspects fraud
2β3%
Do not retry aggressively. Time-of-day and geography matter β a 3 AM charge from an unusual location gets flagged more often. Retry during business hours.
30β50% with timing optimization
The "Do Not Honor" Problem: Solving the Black Box
Code 05 / do_not_honor / generic_decline deserves special attention because it's both the most common and the least informative decline code in subscription billing.
Why "Do Not Honor" Is So Common
When a bank declines a transaction but doesn't want to reveal the specific reason (privacy, competitive reasons, or simply lazy classification), they return code 05. It's a catch-all that can actually mean:
Insufficient funds (the bank just doesn't say so)
Velocity limit exceeded
Temporary security hold
Risk scoring threshold exceeded
Card restrictions (e.g., international transactions blocked)
Account under review
Recovery Strategies for "Do Not Honor" by Pattern
First-time failure, customer is active
Temporary hold or insufficient funds
Retry in 24β48 hours, different time of day
Repeat failures on same day each month
Insufficient funds, timing-related
Shift retry to post-payday window
Failure occurs at unusual hour (3 AM local)
Fraud risk scoring
Retry during 9 AMβ12 PM local time
New card recently added
Issuer restriction on new cards
Wait 5β7 days, then retry
International card, domestic merchant
Cross-border risk block
If possible, route through local acquirer
Failure after period of successful charges
Temporary bank hold or security review
Retry in 48β72 hours
This is where ML models shine. A human looking at "Do Not Honor" sees a dead end. A model that has analyzed millions of these declines across card types, issuers, geographies, and time patterns can predict the underlying cause and apply the right recovery strategy.
FlyCode's internal classifiers disaggregate generic decline codes using hundreds of data points per transaction β turning a black box into an actionable recovery plan.
Card Account Updater and Network Tokens: The Silent Heroes
Before you ever send a dunning email for an expired card, make sure you've enabled the tools that can fix it automatically.
Automatic Card Update Mechanisms
Card Account Updater (CAU)
Automatically replaces expired card details with new ones from the network
Visa VAU, Mastercard ABU β available through Stripe
Prevents 60β80% of expired card failures
Network Tokenization
Creates a persistent token that updates automatically when the physical card changes
Visa, Mastercard β supported by Stripe
Reduces card-on-file failures by 2β5% across all types
Backup card charging
Automatically charges an alternate card on file when the primary fails
Not native in Stripe β available via FlyCode
Recovers 10β15% of failures that would otherwise require customer action
Implementation check: Network Tokenization and Card Account Updater should be active by default on most Stripe accounts. Verify by checking if you're seeing card_updated events in your webhook logs. If you're not seeing them, contact Stripe support.
Recovery Timing Optimization: When to Retry Each Code
Timing isn't just "wait and try again." Different decline types have different optimal retry windows.
Optimal Retry Timing by Decline Type
Insufficient funds
48β72 hours (wait for payday)
5β7 days (next payday cycle)
Day 14β15 (mid-month payday)
Dunning email with card update
Processing error
4β12 hours
24 hours
48 hours
Investigate β may indicate integration issue
Do Not Honor
24β48 hours, different time of day
4β5 days, morning hours
7β10 days
If still failing, likely a hard decline β switch to dunning
Issuer unavailable
4β6 hours
12β24 hours
48 hours
Rare to need 3 retries β should succeed quickly
Expired card
Don't retry β wait for CAU update
After 48 hours (CAU may have updated)
5 days
Dunning email with card update link
Authentication required
Don't retry β send auth link
3 days (reminder email)
7 days (urgency email)
In-app paywall or feature restriction
Conclusion: Stop Treating All Declines the Same
The single biggest mistake in payment recovery is applying the same retry schedule and communication sequence to every failed payment. An insufficient funds decline and an expired card decline require fundamentally different responses.
The companies that recover 70β90% of their failed payments do three things differently: they classify every decline by type and adjust their strategy accordingly, they exhaust silent retries before involving the customer, and they use ML models that learn from their specific transaction patterns β not from the global average.
Take action:
https://www.flycode.com/churn-audit-failed-payments β Get a free payment audit β See your decline code distribution and recovery rate by type.
https://www.flycode.com/revenue-recovery-calculator β Calculate your recovery ROI.
https://marketplace.stripe.com/apps/flycode-payments β Install FlyCode for Stripe.
Related Reading
https://www.flycode.com/blog/stripe-generic-decline-code-what-it-means-why-it-happens-and-how-flycode-recovers-the-revenue
https://www.flycode.com/blog/the-do-not-honor-decline-code-what-subscription-businesses-need-to-know
https://www.flycode.com/blog/what-are-issuer-declines-in-stripe-failed-payment-report
https://www.flycode.com/blog/subscription-ghosting-when-"insufficient-funds"-steals-your-mrr
https://www.flycode.com/blog/how-to-deal-with-failed-payments-if-you-re-using-stripe
Last updated
Was this helpful?