# Stripe: expired_card (the card has expired)

> Stripe returns expired_card when the card is past its expiry date. Ask for another card, let subscribers update theirs, and catch typed date errors separately.

Canonical: https://app369.com/fix/stripe-expired-card/
Last updated: 2026-11-09

expired_card is the Stripe error code, also listed among the decline codes, for a card the bank says has expired. Retrying the same card won’t work. Ask the customer for another card, and for saved cards on subscriptions, send them a link to update the card before the next renewal fails too.

**Short answer**

Check error.code for expired_card, show a message that the card has expired, and ask for another one, keeping the same PaymentIntent. For renewals, send the customer to a page where they can replace the card, such as the Stripe customer portal, then pay the open invoice with stripe.invoices.pay. A wrong expiry typed at checkout returns invalid_expiry_month or invalid_expiry_year instead, which a retry with the right date fixes.

Rather not fix it yourself? [**Stripe Billing Fix and Setup**](https://app369.com/fixed-price/stripe-billing-setup/) handles it at a fixed price, agreed before work starts.

## **What expired_card means, and the fix**

1. 01 ### **The card is past its date**
  > “The customer needs to use another card.” [**Stripe, Decline codes (expired_card)**](https://docs.stripe.com/declines/codes) The bank refused the card because it has expired. The customer has to pay with a new card or another payment method.
2. 02 ### **Ask for another card at checkout**
  > “The card has expired. Check the expiration date or use a different card.” [**Stripe, Error codes (expired_card)**](https://docs.stripe.com/error-codes) Stripe’s card forms usually catch a past date before submitting, so at checkout this mostly comes from a saved card. Tell the customer the card has expired and let them enter a new one. Check error.code, because decline_code can be empty for this error.```
if (error?.code === 'expired_card' || error?.decline_code === 'expired_card') {
  showMessage('This card has expired. Use another card to finish paying.');
}
```
3. 03 ### **A saved card expired on a subscription** Renewals fail when the saved card expires. Email the customer a link to update the card, for example the customer portal with payment method updates turned on in its settings. Updating the card doesn’t pay the open invoice by itself: pay it, or wait for the next retry.```
const session = await stripe.billingPortal.sessions.create({
  customer: customerId,
  return_url: 'https://example.com/account',
});
// email session.url to the customer

// after the card is updated
await stripe.invoices.pay(invoiceId);
```
4. 04 ### **A typed date is a different error**
  > “The expiration month is invalid.” [**Stripe, Decline codes (invalid_expiry_month)**](https://docs.stripe.com/declines/codes) If the customer mistyped the month or year, Stripe returns invalid_expiry_month or invalid_expiry_year, not expired_card. Point them at the date field for those.
5. 05 ### **Test the message** In a sandbox, pay with test card 4000000000000069 to get the expired_card decline and check what your checkout shows.

Checked against the vendor’s docs on November 9, 2026: [Stripe docs: Decline codes](https://docs.stripe.com/declines/codes); [Stripe docs: Error codes](https://docs.stripe.com/error-codes); [Stripe docs: Testing](https://docs.stripe.com/testing).

## **Rather hand it over?**

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

- [$950**Stripe Billing Fix and Setup**Subscriptions, webhooks, customer portal and failed payments set up or fixed, tested in Stripe test mode.**See scope and start**](https://app369.com/fixed-price/stripe-billing-setup/)
- [from $450**App Fix Ticket**One reproducible bug in an existing mobile or web app, diagnosed and fixed.**See scope and start**](https://app369.com/fixed-price/flutter-firebase-bug-fix/)
- [from $450**AI-Built App Rescue**A Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.****No issues worth fixing, no charge.**** If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.**See scope and start**](https://app369.com/fixed-price/ai-app-rescue/)

[**All 127 Fiverr reviews**](https://app369.com/reviews/)

Related: [**Stripe processing_error**](https://app369.com/fix/stripe-processing-error/) · [**Stripe incorrect_cvc**](https://app369.com/fix/stripe-incorrect-cvc/) · [**Stripe do_not_honor decline**](https://app369.com/fix/stripe-do-not-honor/) · [**Stripe customer portal not working**](https://app369.com/fix/stripe-customer-portal-not-working/)

Questions

## **More on this error**

<details>

<summary>**Was the customer charged? **+</summary>

No. The bank declined the card, so no money moved.

</details>

<details>

<summary>**Should the app retry a renewal on an expired card? **+</summary>

Not with the same card. Wait until the customer adds a new card, then pay the invoice.

</details>

<details>

<summary>**Can you fix it for me? **+</summary>

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

</details>

A different error?

## **Describe it and get a written quote**

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.

[**Describe your problem **→](https://app369.com/contact/) [**All fixes**](https://app369.com/fix/)