← Decline Codes
Hard Decline

Stripe Decline Code · Glossary

expired_card

expired_card is one of the most straightforward — and most preventable — decline codes in Stripe: the card on file has passed its expiration date and the issuing bank is rejecting every charge attempt against it.

Non-recoverable·Updated May 2026

What It Means

What expired_card actually means.

expired_card is one of the most straightforward — and most preventable — decline codes in Stripe: the card on file has passed its expiration date and the issuing bank is rejecting every charge attempt against it. Unlike insufficient_funds or do_not_honor, there is zero ambiguity here and zero point retrying — the card is dead until the customer updates their payment method with a new one.

Not sure if this code is recoverable for your specific situation? Use the Stripe Failure Lookup →

Why It Happens

The root causes.

  • 1Customer never updated their cardThe most common cause; the card expired and the customer simply forgot to update their subscription payment method, especially on set-and-forget SaaS tools they rarely log into
  • 2Card reissued with new detailsBank issued a replacement card (new number, new expiry) but the old credentials are still on file in Stripe — common after bank security refreshes, card program upgrades, or fraud-related reissuances
  • 3Network tokenization not activeStripe's account updater and network tokens automatically update card details in many cases, but only if you have it enabled and the issuing bank participates in the program — gaps here mean expired cards slip through
  • 4Prepaid or virtual cardsThese often have short expiry windows (6–12 months) and are never reissued, creating a silent expiration cliff for customers who used one-time virtual cards at signup
  • 5Long-inactive subscriptionsAnnual plan customers billed once per year are most exposed — a card valid at signup may expire before the next billing cycle hits

What NOT to Do

Common mistakes that make it worse.

Don't retry the same card — ever

expired_card is a hard decline, full stop. No retry interval, no paycheck cycle logic, no "try again in 3 days" — the card is expired and will be declined every single time until the customer updates it. Every retry wastes an attempt, adds latency to your recovery, and signals poor billing hygiene to card networks.

Don't send a generic payment failure email

"Your payment failed — please try again" is the worst possible message for an expired card. The customer can't "try again" — they need to go into their account and enter a new card. Your email subject line, body copy, and CTA must be specific: update your payment method, not "retry" or "check your bank."

Don't wait more than 24 hours to send the first email

Unlike insufficient_funds where you want to wait a few days, expired_card requires immediate action. Every hour of delay is revenue not collected. The customer already knows their card expired — they just haven't connected it to your subscription yet.

Retry Timing

Optimal retry schedule.

There is no retry timing for expired_card — there is only a card update sequence. All your automation effort goes into driving the customer back to update their payment method, not into scheduling retries.

Recovery Benchmark

What good looks like.

MetricResult
Recovery with proactive pre-expiry email55–70% (before failure even occurs)
Recovery after failure — email sequence only45–60%
Recovery with in-app + email combined65–75%
Recovery with SMS/WhatsApp added+10–15% additional lift
Recovery with no outreach (passive)~5–10%
Median time to recovery2–5 days after first email

A best-in-class dunning system should recover 65%+ of expired card failures — and prevent another 30–40% entirely through pre-expiry interception. If you're recovering less than 40%, your email sequence is either too slow, too vague, or missing an in-app touchpoint.

At Scale

How to handle it at scale.

Automated

  • Webhook trigger: invoice.payment_failed → check failure_code === 'expired_card' → tag customer as "expired card" segment — completely separate dunning track from soft declines
  • Zero retries: Remove this segment from all retry schedulers entirely — retrying an expired card wastes Stripe API calls and pollutes your retry success metrics
  • Email Day 0: Fire within 60 minutes of failure. Subject line formula: "Action needed — your [Product] card expired" — personalized with card last 4 digits, expiry date shown, and a single bold CTA button to the payment update page
  • In-app banner: Inject a persistent top-of-page banner on every authenticated session from Day 1 — triggered by subscription status === 'past_due' and failure_code === 'expired_card'
  • Pre-expiry automation (most important): Run a monthly cron job querying stripe.customers.list() → filter for cards expiring within 60 days → enroll in a 3-email pre-expiry sequence. This is your #1 lever for this code
  • Stripe Account Updater: Enable Stripe's automatic card updater in your Dashboard settings — it silently updates card details for participating banks before expiry hits, eliminating a chunk of expired card failures with zero customer action required

Manual Escalation

  • High-ACV accounts: Personal outreach on Day 3 if no update — a CSM or founder email (not automated) to a $300+/month account is worth every minute; mention the card by last 4 digits to show attentiveness
  • Annual plan customers: Flag all annual subscribers 90 days before renewal and assign manual review — a card valid at last year's billing may be expired by renewal date; catch this before the charge fails, not after
  • No-login customers (30+ days inactive): If a customer hasn't logged in and their card expired, email alone may not reach them — consider a LinkedIn message, WhatsApp, or phone call before cancelling access

FAQs

Frequently asked questions.

What does the Stripe expired_card decline code mean?

The Stripe expired_card decline code means the credit or debit card on file has passed its expiration date and the issuing bank is rejecting all charge attempts. The card cannot be retried — the customer must update their payment method with a new, valid card.

What causes an expired_card error in Stripe?

Common causes include the customer forgetting to update their card after expiry, a bank reissuing a card with new details after a fraud event or program upgrade, prepaid or virtual cards with short expiry windows, Stripe Account Updater not being enabled, or annual plan customers whose card expired between billing cycles.

Should I retry a payment after a Stripe expired_card error?

No. expired_card is a hard decline and retrying will always fail until the customer updates their payment method. All recovery effort should go into a fast, clear card update email sequence — not retry scheduling.

How do I prevent expired_card failures before they happen?

Enable Stripe's Account Updater to automatically refresh card details for participating banks. Additionally, run a monthly query of your Stripe customers to identify cards expiring within 60 days and send a proactive pre-expiry email sequence. This pre-expiry approach eliminates 30–40% of expired card failures before they reach your billing system.

What is the recovery rate for Stripe expired_card failures?

With a proactive pre-expiry email sequence, 55–70% of at-risk cards can be updated before a charge fails. After a failure, combining email, in-app banners, and SMS achieves 65–75% recovery. Without any outreach, passive recovery is only around 5–10%.

Before you retry

Most expired_card failures are retried on the wrong schedule — which recovers the payment about 30% of the time. The other 70% leaves permanently. See what this code is actually costing at your MRR before deciding how to handle it.

See what expired_card costs me →

Stop leaving revenue on the table

expired_card can't be retried — but it can be caught earlier.

Recurflux handles code-specific retry scheduling, adaptive dunning, and dispute intelligence across all 30 Stripe decline codes. Connect in under 5 minutes.