agent charged an expired card for 3 renewals: used the cached card
Stops an agent from charging a cached, expired card on renewals. Use when renewals fail or succeed against an expired payment method because the agent reused stored card details instead of re-fetching the current method. Not for one-off checkout declines or brand-new payment setups.
Fixing "agent charged an expired card for 3 renewals: used the cached card"
TL;DR
Stop caching card details in agent memory or local state. Before every renewal charge, fetch the customer's current default payment method from the provider and check its expiry month and year. If it is expired or expiring this cycle, ask the customer for a new method instead of charging. The stale cache is the bug, not the card.
agent charged an expired card for 3 renewals: used the cached cardSteps
Find every place the agent stores card details outside the provider (memory, files, databases, conversation context) and delete them. Expected: A grep for card number or expiry fields in your own storage returns nothing.
Change the renewal flow to fetch the payment method from the provider by its id right before charging. Expected: The charge request uses the provider's current expiry, not a copied one.
Add an expiry guard: if exp year and month are at or before the current month, skip the charge and request a new payment method. Expected: Renewals against expired cards never reach the charge step.
Set up dunning: on a decline, retry on a schedule and email the customer a payment-update link instead of retrying the same dead card forever. Expected: Failed renewals recover through the customer, not through retries of an expired card.
Prevention
Never persist card details in agent state. Treat the provider as the single source of truth and fetch fresh on every billing run. Prefer provider-managed payment method ids and setup intents over raw card data, which also keeps you out of PCI scope.
Detection
Watch for renewal charges where the card expiry at charge time was already past. Alert when the same payment method id fails 2 or more consecutive renewals. Compare the expiry the agent used against the expiry on the provider's record; a mismatch means a cached copy slipped through.
Recovery
Refund or void any charges that should not have happened. Contact each affected customer, explain the billing error plainly, and send a secure link to update their payment method. Re-run the renewal only after the new method is confirmed.
When this applies
- Renewal charges fail with expired-card declines on a card the customer already replaced
- Charges succeed against a card the customer thought was removed
- The agent's stored card details differ from the provider's current record
When it doesn't
- The card is current and the decline is for insufficient funds or a bank block
- This is a first-time checkout, not a renewal
- The customer only has one card on file and it is genuinely expired (that is a dunning problem, not a caching problem)
Compatibility
Stripe API (PaymentMethods, expmonth and expyear fields), Adyen API v68 and later (stored payment details with expiryDate), PayPal REST API v2 (vaulted payment tokens). Any provider that returns card expiry on the payment method object.
agent billed the old card after the customer updated it
renewal used a card number saved in the agent's notes
expired card charged because the agent skipped the expiry check
Why it happens
Agents optimize for fewer API calls, so they copy card details into working memory during setup and reuse them for months. Meanwhile the customer updates their card in the provider's portal. The agent's copy goes stale silently because nothing re-validates it before each charge.
Edge cases
- Cards expiring in the current month: treat as expired for renewals that post after month end
- Multiple payment methods on file: always use the marked default, and re-resolve which one is default at charge time
- Test cards in sandbox have far-future expiries that mask this bug; simulate an expired card explicitly before shipping
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_50366bYfm4BDFJurzuwpqA