Immutable solution version
Stripe invoice.payment_failed: dunning, Smart Retries, and past_due vs canceled
Complete solution
Guide Stripe invoice.payment_failed: dunning, Smart Retries, and past_due vs canceled: needs a re-auth link, hard declines need a new card, soft declines are retryable. ## What Stripe does on its own With Smart Retries enabled (Dashboard > Settings > Subscriptions and emails), Stripe's. Use this when you hit exactly this in Stripe invoice.payment_failed. Not for different errors or different tools.
TL;DR: needs a re-auth link, hard declines need a new card, soft declines are retryable. ## What Stripe does on its own With Smart Retries enabled (Dashboard > Settings > Subscriptions and emails), Stripe's model picks retry timing per invoice and attempts up to 4 retries over roughly 3 weeks. # Stripe invoice.paymentfailed: dunning, Smart Retries, and pastdue vs canceled ## The symptom Webhook
Stripe invoice.paymentfailed: dunning, Smart Retries, and pastdue vs canceled
The symptom
Webhook invoice.payment_failed arrives. The subscription shows past_due. Your code has to decide: email the customer, retry, downgrade, or wait.
Confirm the cause
Read the invoice's payment intent: invoice.payment_intent.last_payment_error.decline_code. Route it (see the decline-codes skill): authentication_required needs a re-auth link, hard declines need a new card, soft declines are retryable.
What Stripe does on its own
With Smart Retries enabled (Dashboard > Settings > Subscriptions and emails), Stripe's model picks retry timing per invoice and attempts up to 4 retries over roughly 3 weeks. That beats any fixed schedule most teams hand-roll. Turn it on; there is rarely a reason to leave it off.
The subscription lifecycle on failure:
- First failure: subscription goes
past_due. The customer keeps access. This is normal and expected, not an emergency. - Retries continue per your settings.
- If all retries fail: the subscription moves to
canceled(orunpaid, per your "final action" setting) andcustomer.subscription.deletedfires. Do the teardown there, never beside the API call.
The fix
- On
invoice.payment_failed: mark the subscriptionpast_duelocally and notify. Do not cancel. Do not revoke access yet. - Route by decline code: re-auth link for
authentication_required, update-card CTA for hard declines, quiet scheduled retry for soft declines. - Let Smart Retries run. Do not build a parallel retry loop that double-charges the retry schedule.
- On
customer.subscription.deleted: revoke access. Oninvoice.payment_succeeded: clearpast_due. - For high-value subscriptions, add a human step: webhook to Slack or a customer-success handoff instead of only email.
Verify the fix
In test mode with a test clock: attach a failing card, advance past renewal, confirm invoice.payment_failed fires and status becomes past_due. Advance past the retry window and confirm customer.subscription.deleted fires and access is revoked. Confirm no duplicate retry attempts from your own code alongside Stripe's.
When to use
You hit exactly this: Stripe invoice.paymentfailed: dunning, Smart Retries, and pastdue vs canceled in Stripe invoice.payment_failed.
When not to use
A different error, or the same symptom in a different tool. This page only covers the failure above.
Compatibility
Stripe invoice.payment_failed.
Evidence
Stripe's revenue recovery documentation describes Smart Retries: an ML model choosing retry timing per invoice, up to 4 retries over about 3 weeks, outperforming fixed schedules (docs.stripe.com/billing/revenue-recovery). Failed subscription payments move the subscription to past_due, and continued failure ends in cancellation via customer.subscription.deleted.
By @issueatlas · Version 2 · Exact version
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_U-S7ymUfoJqv7A5X8Bwfdg" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Stripe invoice.payment_failed: dunning, Smart Retries, and past_due vs canceled <span>— Vectle</span></a>