Decline Codes Fresh
When a charge fails, Stripe returns a decline_code on the error object. Use these to show appropriate messages and determine next steps.
How decline codes work
Decline codes appear on card_error type errors. The error object includes:
type: "card_error"— identifies this as a card declinedecline_code— the specific reason codemessage— a human-readable message (safe to show users for card errors)charge— the ID of the failed charge
javascript
try {
const paymentIntent = await stripe.paymentIntents.confirm(id);
} catch (err) {
if (err.type === 'StripeCardError') {
console.log(err.decline_code); // e.g., 'insufficient_funds'
console.log(err.message); // safe to show the customer
}
}Card decline codes
| Decline code | Description | Next steps |
|---|---|---|
authentication_required | Transaction requires authentication (3DS) | Retry with 3DS flow; for off-session, ask customer to authenticate on-session |
authentication_not_handled | Auth required but not performed | Run 3DS / SCA flow before retrying |
approve_with_id | Payment cannot be authorized | Retry once; if still failing, customer contacts issuer |
call_issuer | Declined for unknown reason | Customer contacts their card issuer |
card_not_supported | Card doesn't support this purchase type | Customer contacts issuer to enable this purchase type |
card_velocity_exceeded | Balance, credit limit, or transaction limit exceeded | Customer contacts issuer |
currency_not_supported | Card doesn't support this currency | Customer checks with issuer |
do_not_honor | Declined for unknown reason | Customer contacts issuer |
duplicate_transaction | Identical amount and card submitted recently | Check if a recent payment already exists |
expired_card | Card has expired | Customer uses another card |
fraudulent | Stripe suspects fraud | Present as generic_decline — don't reveal fraud detection to customer |
generic_decline | Unknown reason or blocked by Radar | Customer contacts issuer |
incorrect_address | Address entered is incorrect | Customer retries with correct address |
incorrect_cvc | CVC number is incorrect | Customer retries with correct CVC |
incorrect_number | Card number is incorrect | Customer retries with correct card number |
incorrect_pin | PIN is incorrect (card-present only) | Customer retries with correct PIN |
incorrect_zip | Postal code is incorrect | Customer retries with correct postal code |
insufficient_funds | Card has insufficient funds | Customer uses alternative payment method |
invalid_account | Card or account is invalid | Customer contacts issuer |
invalid_amount | Payment amount is invalid or exceeds limit | Customer checks with issuer |
invalid_cvc | CVC is incorrect | Customer retries with correct CVC |
invalid_expiry_month | Expiration month is invalid | Customer retries with correct expiry |
invalid_expiry_year | Expiration year is invalid | Customer retries with correct expiry |
invalid_number | Card number is incorrect | Customer retries with correct card number |
invalid_pin | PIN is incorrect | Customer retries with correct PIN |
issuer_not_available | Card issuer couldn't be reached | Retry the payment; if still failing, customer contacts issuer |
lost_card | Card reported lost | Present as generic_decline |
merchant_blacklist | Matches a value on your block list | Present as generic_decline |
new_account_information_available | Card or account is invalid | Customer contacts issuer |
no_action_taken | Declined for unknown reason | Customer contacts issuer |
not_permitted | Payment not permitted | Customer contacts issuer |
offline_pin_required | Card requires a PIN | Customer inserts card and enters PIN |
online_or_offline_pin_required | Card requires a PIN | Prompt for Online PIN if reader supports it; otherwise customer inserts and enters PIN |
pickup_card | Card may be reported lost or stolen | Customer contacts issuer |
pin_try_exceeded | Too many incorrect PIN attempts | Customer uses another card or payment method |
processing_error | Error during card processing | Retry the payment; if still failing, try again later |
reenter_transaction | Issuer couldn't process for unknown reason | Retry; if still failing, customer contacts issuer |
restricted_card | Card restricted (may be lost or stolen) | Customer contacts issuer |
revocation_of_all_authorizations | Declined for unknown reason | Customer contacts issuer |
revocation_of_authorization | Declined for unknown reason | Customer contacts issuer |
security_violation | Declined for unknown reason | Customer contacts issuer |
service_not_allowed | Declined for unknown reason | Customer contacts issuer |
stolen_card | Card reported stolen | Present as generic_decline |
stop_payment_order | Declined for unknown reason | Customer contacts issuer |
testmode_decline | Stripe test card number used in live mode | Use a real card for live payments |
transaction_not_allowed | Declined for unknown reason | Customer contacts issuer |
withdrawal_count_limit_exceeded | Customer exceeded balance or credit limit | Customer uses alternative payment method |
mobile_device_authentication_required | Transaction requires device authentication | Retry by tapping mobile device again |
Sensitive decline codes
Do NOT reveal the actual reason for these codes to customers. Present all of them as a generic decline:
fraudulentlost_cardstolen_cardmerchant_blacklist
Show the customer: "Your card was declined. Please contact your card issuer or use a different payment method."
Local payment method decline codes
| Decline code | Description | Next steps |
|---|---|---|
partner_generic_decline | Payment provider declined | Customer contacts payment provider |
invalid_customer_account | Can't charge customer's account | Customer resolves issue with their account |
payment_limit_exceeded | Order exceeds account limit | Customer resolves limit with payment provider |
invalid_billing_agreement | Billing agreement is invalid | Payment method is invalid; retries won't succeed |
processing_error | Payment provider processing error | Retry |
insufficient_funds | Insufficient funds with payment provider | Customer uses alternative |
currency_not_supported | Currency not supported by payment provider | Retries won't succeed |
invalid_amount | Amount not allowed | Retries won't succeed |
compliance_violation | Violates terms of service or applicable laws | Retries won't succeed |
duplicate_transaction | Identical transaction submitted recently | Check for existing payment |
recurring_not_supported_by_bank | Bank doesn't support recurring for this method | Customer selects a bank that supports recurring |
Handling declines in code
javascript
const express = require('express');
const stripe = require('stripe')('sk_test_YOUR_KEY');
const app = express();
app.post('/charge', async (req, res) => {
try {
const paymentIntent = await stripe.paymentIntents.confirm(req.body.paymentIntentId);
res.json({ success: true });
} catch (err) {
if (err.type === 'StripeCardError') {
// Safe to show to customer
res.status(402).json({
error: err.message,
decline_code: err.decline_code,
});
} else {
// Don't expose internal errors to customers
console.error(err);
res.status(500).json({ error: 'An error occurred. Please try again.' });
}
}
});Retrying declined charges
| Decline code | Retryable? | Notes |
|---|---|---|
insufficient_funds | Yes (later) | Customer may top up account |
processing_error | Yes | Transient error |
issuer_not_available | Yes | Transient error |
card_declined / generic_decline | Yes (once) | Try once; if declined again, ask for alternate |
expired_card | No | Needs new card |
invalid_cvc / incorrect_cvc | No | Needs correction |
lost_card / stolen_card | No | Card is invalid |
fraudulent | No | Don't retry |