Diagnostic guide
lovable stripe subscription not working
Generated apps get the happy path right and the edges wrong. Checkout works, the first payment often works, and then the parts that only matter later (cancellations, refunds, plan changes) turn out never to have been wired at all. None of them announce themselves.
most likely causes, in order
01Only the creation event is handled+
how it looks
New subscriptions work. Cancellations do nothing. Someone who cancelled in August still has access.
how to check
Search your webhook handler for customer.subscription.deleted. In generated apps it is frequently absent.
the fix
Handle deleted, updated, and charge.refunded, not just checkout.session.completed.
02Service-role key missing in the webhook+
how it looks
The handler runs cleanly and updates nothing. Zero rows affected.
how to check
The webhook must use the service-role key. With the anon key, RLS silently drops the write: there is no authenticated user in a webhook.
the fix
Server-side only. If it can reach the browser, rotate it today.
03The endpoint points at a preview deployment+
how it looks
It worked while you were building and stopped after you shipped.
how to check
Compare the registered webhook URL against your production domain.
the fix
Update it, then replay the failed events.
04The access column and the gate disagree+
how it looks
subscribed is true, the UI shows free.
how to check
Read the actual condition in the dashboard component. Generated code often checks a different column than the one the webhook writes.
the fix
One source of truth, read everywhere.
05Test-mode keys in production+
how it looks
Real payments never arrive. Everything looks fine in testing.
how to check
Live keys start with sk_live. The webhook signing secret is per-endpoint and per-mode.
the fix
Separate both by environment.
check it yourself
The two states worth checking on a Supabase build. Run this in your SQL editor, adjusting the table and column names to match your schema.
-- paid, no access: they will email you select email, stripe_customer_id, subscribed, created_at from public.subscribers where stripe_customer_id is not null and subscribed = false; -- access with no active record: nobody will ever email you select email, subscribed, subscription_tier, subscription_end from public.subscribers where subscribed = true and (subscription_end is not null and subscription_end < now());
what this does not tell you
The second query is the one worth running twice. Anyone it returns has been using your product for free since their subscription lapsed, and there is no version of that story where they tell you.
Read-only, both sides. Three findings free, no account.
related
Stripe webhook not updating database
Your Stripe webhook returns 200 but the row never changes. The five causes, how to tell them apart, and the SQL to find everyone already affected.
Customer paid but has no access
Someone paid and got nothing. Fix the one in front of you in five minutes, then find out how many others are in the same state.