← Guides

Stripe decline codes, in plain English

Last updated 12 October 2026

When Stripe can’t charge a card, it records why on the payment: a decline_code that says what went wrong, and usually an advice_code that says what to do next. Most failed-payment emails ignore both and send everyone the same “your payment failed”. But no money in the account, a bank block and an expired card are three different problems, and each one has its own fix.

Where Stripe puts the reason

On the PaymentIntent behind the failed invoice, under last_payment_error. A subscription reaches it through its latest invoice:

subscription.latest_invoice.payments.data[0].payment.payment_intent
  → payment_intent.last_payment_error.decline_code   // why
  → payment_intent.last_payment_error.advice_code    // what next

invoice.charge no longer exists on current API versions; invoice.payments replaced it. Stripe also stops expanding at four levels, so the PaymentIntent is one more request per failing customer.

Start with the advice code

Stripe sorts every decline into one of three next steps, and it keeps that sorting up to date. That makes it the safest thing to decide on. The decline code is for wording.

advice_codeMeansTell the customer
try_again_laterA retry may workTell them when the retry is, and give them the invoice’s payment link in case they’d rather pay now.
confirm_card_dataCard details need re-enteringAsk them to re-enter their card details on the payment page. Nothing is wrong with their bank.
do_not_try_againNeeds a different cardAsk for a different card, or for a call to their bank. Don’t promise a retry, because it won’t happen.

Two catches:

  • A Radar block has no advice code at all. A charge Radar stops comes back as fraudulent, with no advice_code. Falling back to “try again later” for those promises a retry that Stripe blocks every time. Any code that Stripe never retries (listed below) means “don’t try again”.
  • The advice code is a plain string, not a fixed list. If a fourth value turns up, give it your safest email. Never use the cheerful retry email as the default.

Then word it with the decline code

Stripe gives insufficient_funds and generic_decline the same advice code. If you only look at the advice code, both get the same email, so the decline code is what lets you tell the customer what actually happened:

  • No money: insufficient_funds. Timing is the message here. Stripe runs the retry schedule and you can’t move a charge to payday, but you can send the email near payday with the invoice’s payment link.
  • A limit at the bank: card_velocity_exceeded, withdrawal_count_limit_exceeded. These look like no money, but Stripe’s own advice is to call the bank or switch cards. A retry hits the same ceiling.
  • The card needs replacing: expired_card, incorrect_number, invalid_number, invalid_expiry_month, invalid_expiry_year. The customer can fix these alone on the payment page.
  • The card was reissued: new_account_information_available, invalid_account. They need the new card’s details.
  • The bank blocked it: call_issuer, do_not_honor, transaction_not_allowed, card_not_supported, restricted_card. Only a call to the number on the back of the card, or another card, moves these.
  • No reason given: generic_decline. Stripe says banks file most declines here, so write this email first and make it good. Exact reasons are a bonus.

Codes Stripe never retries

For these codes, Stripe keeps a retry on the calendar and keeps counting attempts, but never runs the retry until the customer adds a new payment method. The invoice shows a next retry date that will never come:

incorrect_numberlost_cardpickup_cardstolen_cardauthentication_requiredtransaction_not_allowedrevocation_of_authorizationrevocation_of_all_authorizationsfraudulentmerchant_blacklist

Never send these customers “we’ll try again on…”. Only a new card helps. Why Stripe isn’t retrying a failed payment covers what that does to your past-due list.

Four you must not repeat to the customer

Stripe is explicit: tell the customer these were a plain decline, never the real reason. You should still read them yourself, though. merchant_blacklist means your own block list stopped the charge, and a card reported stolen isn’t worth the chase an ordinary decline is.

fraudulentlost_cardstolen_cardmerchant_blacklist

Every code

decline_codeWhat it meansStripe retries
fraudulentdon’t tell the customerBlocked as suspected fraudNever: needs a new card
merchant_blacklistdon’t tell the customerYour own block list stopped itNever: needs a new card
lost_carddon’t tell the customerCard reported lostNever: needs a new card
stolen_carddon’t tell the customerCard reported stolenNever: needs a new card
pickup_cardBank asked for the card backNever: needs a new card
insufficient_fundsNot enough money in the accountCan
withdrawal_count_limit_exceededHit their withdrawal limitCan
card_velocity_exceededToo many charges on this cardCan
expired_cardCard has expiredCan
incorrect_numberCard number is wrongNever: needs a new card
invalid_numberCard number is wrongCan
invalid_expiry_monthExpiry date is wrongCan
invalid_expiry_yearExpiry date is wrongCan
incorrect_cvcSecurity code is wrongCan
invalid_cvcSecurity code is wrongCan
new_account_information_availableCard was reissuedCan
invalid_accountCard was reissuedCan
call_issuerTheir bank blocked itCan
do_not_honorTheir bank blocked itCan
transaction_not_allowedTheir bank blocked itNever: needs a new card
card_not_supportedCard not supported hereCan
restricted_cardCard is restrictedCan
processing_errorError at the bank, not the cardCan
generic_declineDeclined, no reason givenCan
authentication_requiredAuthentication requiredNever: needs a new card
revocation_of_authorizationRevocation of authorizationNever: needs a new card
revocation_of_all_authorizationsRevocation of all authorizationsNever: needs a new card

Before you send anything

  • Turn off Stripe’s own failed-payment emails in Billing settings if you write your own, or the customer gets two.
  • Not every past-due invoice was declined. A payment waiting on 3-D Secure has no decline code, because nothing was declined. Its PaymentIntent is at requires_action, and it needs the customer to approve the payment, not a new card. Check the PaymentIntent’s status before you read a decline code.
  • Don’t retry on your own past eight attempts. Stripe recommends at most eight per charge. More can look like fraud and get legitimate charges declined.

Gradsey’s Failed payments report does all of this for every failing card in your account. It shows each customer with their decline code, Stripe’s advice, the next retry (only if one will really run) and an email worded for their situation, ready to send from your Gmail.

Gradsey does this for your own Stripe account