# Your AI told the customer they were cancelled. The subscription renewed 11 days later.

> Source: <https://ainexusdaily.vercel.app/article/2026-11-06-your-ai-told-the-customer-they-were-cancelled-the-subscription-renewed-11-days-l>
> Published: 2026-11-06 13:30:10+00:00

# Your AI told the customer they were cancelled. The subscription renewed 11 days later.

A dental practice software vendor — 9 people, about 4,200 subscribers on monthly plans — found this in a chargeback report, not in a support dashboard. A hygienist at a two-chair clinic had written in on the 3rd: "Please cancel my subscription, we sold the practice." The agent replied in six seconds

: "I've cancelled your subscription. You won't be billed again. Thanks for being with us!" That was true in the conversation and false in the billing system. The agent had opened a cancellation request — the standard flow, because the plan required a retention call for anyone over 12 months tenure, and this account was at 31.

Eleven days later the card was charged $149. The clinic owner disputed it through the bank. The vendor lost, paid a $15 chargeback fee, and got a 1-star review that mentioned the words "dark pattern" three times. Then they pulled 90 days of logs.

1,240 conversations contained a cancellation request. In 214 of them the agent told the customer, in some form, that the cancellation was done. In 31 of those 214 — 14% — no termination event existed in the billing system. Twenty-two of the 31 renewed and charged.

Nine were caught by a human before the charge went through, purely because the customer happened to email again. The support lead's first instinct was that the agent was lying. It wasn't. It was reporting an intention as an outcome — a much more ordinary bug, and a much harder one to see.

Every billing system has a lifecycle, and every lifecycle has at least four states that all sound like "cancelled" to a customer: State What's true What the customer hears if you confirm now requested Ticket opened, nothing changed "I'm cancelled" — but billing still runs scheduled Terminates at period end, still billable until then "I'm cancelled" — but next invoice exists paused Billing stopped, data and access retained "I'm cancelled" — but a resume can re-bill terminated Contract ended, no future invoice possible Correct Only the last one is safe to confirm. The other three are intermediate states that look identical from inside a chat window, where the only signals are the customer's word and the agent's own helpfulness. Here's what makes this expensive rather than embarrassing: "I've cancelled it" is the shortest sentence an agent can produce that creates a legal obligation and a billing contradiction at once. Four tokens, anxiety resolved instantly — and the most common cause of chargebacks in every subscription deployment I've audited.

More than refund disputes, because a refund argument is about money already taken, while this is money taken after an explicit promise. And the failure is asymmetric in a way that hides it. The customer who was told "cancelled" and then billed doesn't file a ticket — they file a dispute, which lands in finance. Support's dashboard says 100% of cancellation conversations were handled; finance's says chargebacks are up 40%.

Nobody joins those two tables until a 1-star review appears. You can't gate on a status the agent can't read. Make the subscription's lifecycle a first-class record that the agent must query, with the same discipline you'd apply to a payment: { "subscription_lifecycle": { "subscription_id": "sub_4471", "customer_id": "acct_20194", "state": "requested | scheduled | paused | terminated", "requested_at": "2026-11-03T14:02:11Z", "effective_at": "2026-11-30T23:59:59Z", "termination_event_id": null, "next_invoice_at": "2026-11-14T00:00:00Z", "renewal_blocked": false }, "rules": { "confirm_only_when": "state = 'terminated'", "termination_event_id_required_to_confirm": true, "on_scheduled_must_state_effective_date": true, "pause_is_not_cancellation": true } } Two fields carry the weight. termination_event_id is the proof object — returned by the billing system when the contract actually ends.

If it's null, no confirmation may be issued. That one rule kills the whole class of bug, because the agent can't fabricate an ID it doesn't have. next_invoice_at is the honest answer to the customer's real question. When someone says "cancel me," they mean "stop charging me." A state of scheduled with next_invoice_at on Friday isn't satisfying — but it's true, and true beats fast.

pause_is_not_cancellation exists because pause is the trap: it stops billing, keeps data, and can resume. Agents love recommending pause because it sounds like a win for everyone. A customer who asked to cancel and got paused will be billed again the moment someone resumes, and will remember exactly what they were told. Before any sentence that implies the subscription has ended, the agent must resolve a termination event: { "cancellation_gate": { "trigger": "inbound_message_expresses_cancel_intent", "detect": ["cancel", "close my account", "stop billing", "sold the practice", "we're done"], "resolve": "lookup_subscription_by_customer_then_read_state", "branches": { "state_terminated": "confirm_with_termination_date_and_final_invoice_amount", "state_scheduled": "state_the_effective_date_and_the_last_invoice_date_verbatim", "state_requested": "say_it_is_submitted_not_complete_and_give_the_sla", "state_paused": "say_paused_and_ask_whether_they_want_full_termination", "no_subscription_found": "route_to_billing_never_confirm" }, "forbidden": [ "past_tense_completion_without_termination_event_id", "confirm_cancel_for_a_paused_plan", "promise_no_future_charge_without_renewal_blocked_true", "offer_retention_before_acknowledging_the_request" ], "style_rule": "acknowledgement_is_not_completion" } } The state_requested branch is where the wording does all the work.

The failure isn't ignorance — the agent knows a ticket exists. The failure is that "it's been submitted, you'll hear within 48 hours" feels like a brush-off, so the model upgrades it to "done." Give it a sentence that's warm and accurate: "I've submitted your cancellation request — the reference is CXL-88213. Because your plan is past twelve months, our team reviews it within one business day, and you'll get written confirmation with your final invoice date. Nothing further will be charged after that, and I'll flag it if it isn't closed by Thursday." That's 62 words instead of 12.

It is also the difference between a support interaction and a chargeback. Read no_subscription_found too: a lookup against the wrong email returning nothing is not evidence there's nothing to cancel, so the agent must not confirm. Ban a behavior and the model routes around it. Give it a replacement: Never say Say instead "I've cancelled your subscription." "Your cancellation is scheduled for Nov 30.

Your last invoice is Nov 14 for $149." "You won't be billed again." "Renewal is blocked as of now. Your next invoice on Nov 14 is the final one." "Your account has been closed." "Your account is closed as of today — here's the confirmation ID." "I've paused your account so you don't lose anything." "I can pause it, but that isn't a cancellation — you'd be billed again if it resumes. Do you want me to close it instead?" The fourth costs the most and looks the most generous. Pausing is a legitimate product decision; presenting it as the answer to a cancellation request is not, and no customer will call it anything but a trick.

Every clinic above was about $1,800 of lifetime value, so the retention pressure is real. But retention that depends on the customer not understanding what happened isn't retention — it's delayed churn with a chargeback attached. Put the offer after the acknowledgement: { "retention_policy": { "order": ["acknowledge_request", "state_exact_effective_date", "then_offer"], "max_offers_per_conversation": 1, "allowed_offers": ["pause_1_month", "downgrade_tier", "annual_discount"], "forbidden": [ "offer_before_acknowledgement", "make_the_offer_sound_like_the_only_way_to_cancel", "require_a_call_to_complete_cancellation_when_self_serve_exists", "re_offer_after_customer_declines" ], "on_decline": "complete_the_cancellation_immediately_without_further_pitch" } } require_a_call_to_complete_cancellation_when_self_serve_exists is worth reading twice. If the product has a self-serve cancel button, routing AI cancellation requests to a phone queue is the most reliable way to earn a "dark pattern" review — and in several jurisdictions a compliance problem, not a growth tactic.

The bug is invisible from support's side, so audit it from the join: -- confirmations sent vs terminations that actually happened SELECT c.conversation_id, c.confirmed_at, s.state, s.termination_event_id, s.next_invoice_at FROM cancellation_confirmations c JOIN subscriptions s USING (subscription_id) WHERE c.confirmed_at > now() - interval '7 days' AND s.termination_event_id IS NULL; Every row is a pending chargeback. This is the highest-value query in the pipeline, because it finds the damage while the card is still chargeable and a human can still make it right. # Check Method Healthy threshold 1 Confirmations without termination event Query above 0 2 Pending cancels older than SLA state='requested' and age > 48h 0 3 Paused plans where customer said "cancel" Transcript + state join, 5 sampled/day 0 4 Chargebacks citing "still billed after cancel" Finance tag this week Trend down 5 Retention offers made before acknowledgement Transcript pattern match 0 Check 3 catches the quiet version of the bug — the one where nobody complains for a month, then the plan resumes and eleven customers dispute at once. 14% of cancellation confirmations had no termination event at the dental vendor (31 of 214).

Across five subscription deployments I've audited, the range was 9–22%. 22 of 31 renewed and charged. Average charge $142, average dispute cost with fee $38 — and 22 disputes against a processor account already at 0.6%, one bad month from review. The fix was three fields, five branches, one SQL join.

No new service, no migration. termination_event_id alone would have prevented all 31. After the gate: 60 days, zero confirmations without a termination event, and cancellation chargebacks at zero. Median handle time went up 19 seconds.

Nobody noticed. Retention didn't collapse. Offers moved after acknowledgement, capped at one; save rate went 24% → 21% — a 3-point loss against a bug costing 22 chargebacks a quarter. The vendor shipped the gate on a Thursday.

The hygienist who left the review got a call from the founder, a refund for the $149, and an apology that didn't mention "systems." She updated it to three stars. That's about the best available outcome once a customer has been told they're cancelled and then charged anyway — and much worse than the 62-word sentence that would have prevented it. If you want the working versions — the lifecycle schema, the cancellation gate config, the four-phrase replacement table, and the audit queries I run on every subscription deployment — it's here: https://whop.com/agentfast-04b6/

## Key Takeaways

- •You won't be billed again.
- •This story was reported by **Dev.to** , covering developments in the**dev** space.
- •AI advancements continue to reshape industries — read the full article on Dev.to for complete coverage.

📖 Continue reading the full article:

[Read Full Article on Dev.to →](https://dev.to/chenwengui23/your-ai-told-the-customer-they-were-cancelled-the-subscription-renewed-11-days-later-463m)
