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.

Back to decline codes
invalid_expiry_yearNeeds card update
Draft content: this page's explanatory copy is Pass 3 template writing pending a dedicated content pass. The classification badge above and the recovery behavior described below are live, not draft: both come directly from the recovery engine.

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

  • Not necessarily. It means the year value submitted with the charge failed Stripe's validation, which is often a formatting mismatch or typo rather than proof the card is actually past its expiration date.

  • No. The same invalid year produces the same decline on every attempt. Nothing changes until the value itself is corrected.

  • A two-digit versus four-digit year mismatch is a frequent cause, along with plain typos when a customer re-enters their card during a payment update.

  • Keep it simple and non-technical: ask the customer to re-enter their payment details rather than describing the specific validation failure.

  • Both are data-validation failures on the expiration field rather than issuer-side declines, but one flags a bad month value and the other flags a bad year value. Either can stem from the same root cause: a mistyped or mis-formatted expiration date during entry or update.

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