Decline code
Invalid Expiry Year
`invalid_expiry_year` means Stripe rejected the charge because the expiration year submitted with the card is not a valid value, an unreasonable year, a badly formatted one, or one that doesn't match what Stripe's validation expects. Stripe's own definition: "The expiration year is invalid." Like its sibling code for the month field, this points to a submitted-data problem rather than confirmation that the card is dead.
Why it happens
This decline clusters around moments when card details get re-entered: a customer updating an expiring card, a manual card-on-file correction after a failed charge, or a migration of stored payment methods between systems. A common cause is a two-digit versus four-digit year mismatch, where a form field expects "28" and receives "2028" or vice versa, or where a customer simply mistypes the year while updating other fields. Because Stripe validates the year format before the charge reaches the issuing bank, the decline happens early and doesn't reflect anything about the bank's actual records.
How to fix it
Resubmitting the same bad year value will not change the outcome. The charge fails for the same reason on the first attempt and every attempt after it. Automated retries add delay without adding any chance of success. Once a correct, properly formatted year is submitted, though, the charge can proceed normally, so the underlying situation is fixable, just not through persistence. Start by checking your own integration: confirm that whatever collects or updates card details passes the year to Stripe in the expected format, and that any client-side validation rejects obviously wrong years (a year in the past, or a year decades in the future) before submission. On the customer side, the practical move is a direct request to re-enter payment details, framed simply rather than technically. Customers do not need to know the exact validation rule that failed. They need a clear path to fix it.
How Foxhound recovers it
Expired and stale-card declines do not recover through a repeat charge against the same card details. Foxhound skips straight to the card-update path: a hosted, no-login link goes out by email, and an expiring-card alert can fire ahead of the renewal date when the expiration is already visible on the stored card, so the update happens before the charge ever fails.
Questions
See what this looks like on your account
The free audit shows what Stripe already recovered and what is still dying, no signup required.
Run your free audit