Field notes
Stripe fix guides
Stripe fails quietly. A webhook endpoint stops delivering and the payments still succeed, so revenue looks normal while everything that should happen after a payment silently stops. Each note here explains one such problem and gives you a script that finds it through the API, in Python and in Node.js, with tests.
Every other section on this site ships scripts that can repair what they find. These do not, on purpose. A script here holds a credential to a live payments account, where a bug does not cost you a stale cache — it cancels a subscription, refunds a charge, or disables a connected account's payouts.
So they read, they tell you exactly what is wrong, and they print the repair: the endpoint, the parameters, the object id. You run it. Give them a restricted key with read access only and the worst case if one leaks is that somebody learns your webhook URLs.
Stripe
A webhook endpoint sits disabled after days of retries
Events flowed for months, then stopped on one date with nothing in the logs. Stripe disabled the endpoint and no longer retries it.
Refunds nobody issued with reason expired_uncaptured_charge
Stripe writes a Refund of its own when an authorization expires. It lands in the refund rate and turns a capture bug into a customer complaint.
Elevated-risk charges captured with no manual review
Radar scores a charge elevated and authorizes it anyway. Without a review rule nothing stops it, and the first you hear is the chargeback.
Incomplete_expired volume means confirmation is broken
A stack of incomplete_expired subscriptions is not customers changing their mind. Measured against activations it is a broken confirmation step.
Subscriptions frozen on requires_action 3DS authentication
The issuer asked for a 3DS challenge and nobody showed it. The invoice stays open, the subscription stays incomplete, and retries never run.
A Connect platform has no endpoint for connected accounts
Events about your sellers go to a destination nobody created. The endpoint object never returns its scope, so the gap has to be inferred.
Current_deadline passes before anyone collects the fields
A cohort of healthy accounts breaks on one morning. The date that did it sat on every object for weeks, as a timestamp nothing ever sorted by.
A bank account sits at status errored and payouts stop
One payout failed a month ago and none has been attempted since. The destination is frozen, so the failure count stops growing exactly when it matters.
Platform-paused payouts were never unpaused
The investigation closed months ago and the pause is still on. No API call reverses it, no event announced it, and the paper trail is canceled payouts.
Cardholder requirements.past_due keeps every card inactive
The card will not activate and every authorization declines instantly. What is blocking it lives on the cardholder, and often it is only a terms checkbox.
No v2 event destination exists, so thin events never arrive
A v1.* event was added to the webhook endpoint and nothing was delivered. Thin events only reach a v2 event destination, a separate object entirely.
Radar is blocking a large share of your charge attempts
Conversion drops after a rule change. Customers say the card works everywhere else, and it does: the payment never reached their bank.
Payment link hit its completed-session limit and went dead
A campaign link converts for the first N buyers and then stops. The restriction counter reached its cap and the link closed itself, silently.
Billing portal can't cancel, so customers charge back instead
Customers who want out email support, wait, and then dispute the charge. The portal exists; the cancellation feature on it was never switched on.
Undelivered events are aging out of the 30-day window
An outage found three weeks late. The fix takes minutes; the replay is the problem, because the oldest missed events are about to leave the API.
An endpoint subscribes to every event and floods the handler
The webhook route receives dozens of types it has no branch for, and times out at month-end. enabled_events is a wildcard, not a list.
Two endpoints share one URL, so every event is handled twice
Duplicate orders and double fulfilment emails, not reproducible locally. Two enabled endpoints point at the same URL and both signatures verify.
Payout.failed is unsubscribed so failures go unseen for days
Money stops arriving in the bank account and nothing alerts. payout.paid is subscribed, payout.failed is not, and the external account is disabled.
Incomplete subscriptions die silently after 23 hours
A subscription that never gets its first invoice paid sits in incomplete for exactly 23 hours, then expires and cannot be revived.
Active subscriptions with nothing to charge on renewal
Some subscriptions read active but have no payment method in any of the four places Stripe looks. Every renewal fails and no retry is ever scheduled.
Past_due subscriptions keep their access forever
Failed renewals move a subscription to past_due and leave it there. The app only checks for canceled, so the customer keeps everything and pays nothing.
Trials ending in days with no card on file
A cohort of trialing subscriptions has no payment method. On the trial end date they all fail at once, and the default behaviour is silent dunning.
3DS handoff breaks and requires_action intents pile up
PaymentIntents freeze at requires_action when the client never finishes the authentication handoff. No error is raised and no money moves.
PaymentIntents sit in requires_payment_method for weeks
Intents created on page load and never confirmed pile up forever. Checkout starts look healthy while payment volume quietly does not match them.
Radar blocks payments and nobody reads the block reasons
Blocked charges never reach the issuer, so they leave no decline code. A rule written years ago can quietly eat good revenue for months.
Refunds sit failed or requires_action and nobody notices
A refund is not final when created. It can fail days later, and if nothing listens the money leaves your balance and reaches no one.
A connected account sits with charges_enabled false
A seller's checkout stops working and the platform dashboard looks fine, because the account that broke is not the one you are looking at.
Requirements.past_due has already disabled the payouts
A monitor that counts currently_due cannot tell a warning from a broken account, because past_due is a subset of the list it is counting.
Payouts fail with account_closed and nobody is watching
Money leaves your Stripe balance, comes back days later, and the recipient was never paid. The failure_code says which fix applies, if anything reads it.
A connected account has no external account to pay out to
A seller's balance climbs for months with no failed payouts, because no payout was ever attempted. There is nowhere for the money to go.
Disputes are hours from due_by with no evidence attached
Nothing chases a dispute deadline. Read evidence_details.due_by against now and find the ones about to be lost by default rather than on merit.
Disputes closed as lost were never actually contested
A wall of lost disputes hides two different failures. A lost dispute with submission_count 0 was forfeited by the deadline, not decided against you.
Checkout Sessions carry no ID that maps back to your order
A payment lands and nothing on it points at your database. client_reference_id and metadata both default to empty, and nothing warns you.
Duplicate customers share an email and split billing
Stripe does not enforce email uniqueness on Customers. One person ends up with three records, and their card, subscription and invoices sit on different ones.
Draft invoices sit for months and never finalize
A draft invoice has no number, no PDF and no hosted page, and Stripe will not collect on it. Read auto_advance and automatically_finalizes_at.
Open invoices are weeks past due_date and nobody chases
send_invoice bills do not auto-charge. Reminders are an opt-in Dashboard setting, so an overdue invoice can sit at open indefinitely with no follow-up.
Dunning ran out of retries and no attempt is scheduled
After the last Smart Retry, next_payment_attempt goes null and Stripe stops. High attempt_count with nothing scheduled is a customer nobody will ever bill.
Automatic_tax is off on every invoice while selling abroad
automatic_tax.enabled defaults to false, and enabling Stripe Tax in the Dashboard does not touch subscriptions your API create call already made.
A webhook endpoint is pinned to an ancient api_version
Fields the SDK expects are missing from event.data.object, but re-fetching works. The endpoint renders events at the version it was created with.
Payment-creating requests carry no idempotency key
Occasional duplicate charges during network blips, impossible to reproduce. The events show API requests with request.idempotency_key null.
Enabled_events lists event types that are dead or rejected
A handler branch that has not run in a year, and an endpoint update that fails with do not have access to the event types. Two kinds of decay.
Saved cards are already expired but still attached
Renewals fail with expired_card while your UI still shows the card as valid. The automatic updater covers some issuers, and you cannot tell which.
Most Checkout Sessions expire unpaid and nobody is told
Session creation is healthy, revenue is flat, and the only signal is a checkout.session.expired event a full day later that nobody subscribes to.
A deactivated Payment Link is still linked from your site
Customers click buy and land on Stripe's deactivation page. Conversion for that product goes to zero and nothing errors server-side.
No Billing Portal configuration, so portal sessions 400
Manage subscription 500s in production. Test mode and live mode are configured separately, so the portal works right up until the first live click.
Session status is complete but payment_status is still unpaid
Fulfilment fires on checkout.session.completed and the money arrives days later, or not at all. status and payment_status are independent fields.
PaymentMethods are created but never attached to a customer
Reusing a saved card fails with payment_method_unexpected_state. The pm_ id in your database was consumed once and can never be charged again.
Saved cards expire within 60 days and nothing warns anyone
Churn arrives in monthly clusters that map exactly to card expiry dates. The date was in the API for years before the decline that revealed it.
Customers have no email, so Stripe sends no receipts
Cardholders open unrecognised-charge disputes because no receipt ever arrived, and dunning emails for failed renewals go nowhere at all.
SetupIntents are created but never confirmed by the client
The add-a-card flow looks like it worked and no card ever lands on the customer. A pile of SetupIntents sits at requires_confirmation forever.
Live charges fail with testmode_decline from test cards
Real customers get card declined in production. The decline_code is testmode_decline: the deploy carries test keys, or a test-mode ID is hardcoded.
Intents hardcode payment_method_types to card only
The Payment Element renders a bare card form. An explicit payment_method_types array on the intent bypasses dynamic payment methods entirely.
Off-session charges die on authentication_required
Renewals on saved cards fail with authentication_required. The card was attached without a SetupIntent, so no mandate exists and every retry declines.
No payment method domain registered, so wallets never show
Apple Pay and Google Pay work on localhost and vanish in production. The serving domain is not registered with Stripe, so the wallet is filtered out.
Live mode has no webhook endpoint, so nothing is ever pushed
Payments succeed and the application never hears about them. The CLI listener was doing the delivery all along and no live endpoint was ever created.
Events still show pending_webhooks hours after they fired
The endpoint is enabled and the Dashboard is green, but a subset of payments never got processed. Failures look random rather than total.
Customer.subscription.deleted is missing, so access never ends
Cancelled and dunning-exhausted customers keep full product access. Revenue looks fine and entitlements are wrong, usually found by an honest user.
Nothing subscribes to disputes or early fraud warnings
Chargebacks are first noticed when the balance drops or Stripe emails a deadline. The evidence window is already half gone and nothing flagged the fraud.
Metered subscription items with no usage reported
Usage-based subscriptions invoice for zero every cycle. The meter aggregated nothing, because the emitter's event name never matched the meter.
Pending invoice items that never reach an invoice
One-off charges and prorations created months ago that no invoice ever swept up. The revenue exists in Stripe and has never been billed.
No tax registrations while invoicing many countries
Stripe Tax is on, calculation succeeds, every invoice shows zero tax. Without a registration in the buyer's country there is nothing to calculate.
Prices left at tax_behavior unspecified break tax math
Stripe cannot tell whether the amount already includes tax, so the tax is wrong or the line cannot be added to an automatic tax invoice at all.
Radar reviews sit open for days while funds stay at risk
The review queue grows and nobody works it. Flagged payments ship anyway, and any uncaptured authorization is released at seven days.
Highest-risk charges succeed instead of being blocked
An allow rule overrides Stripe's own defaults. The built-in highest-risk block rule looks enabled and quietly does nothing at all.
Charges captured after AVS and CVC verification failed
The issuer approved a payment whose postal code and security code did not match. Stripe records the failure and, by default, does nothing with it.
No statement descriptor, so customers dispute what they see
A trickle of unrecognized and duplicate disputes from real customers. The line on their statement does not carry your name, and never did.
The transfers capability is inactive so every transfer 400s
Transfers fail for one seller while every other account works. charges_enabled is true; the capability that moves the money is a different field.
A payout schedule left on manual strands the balance
A seller's balance climbs with a valid bank account and no requirements outstanding, because manual means Stripe never initiates the payout. Your code must.
Accounts stall at details_submitted false after link expiry
A long tail of accounts that never opened. The onboarding link expires within minutes and is strictly single use, and nothing minted a new one.
Requirements.errors explains the rejected document
A user uploads their passport four times and your UI says pending. The code saying why the last one was rejected is already on the account object.
Unpaid subscriptions keep access and stop billing entirely
unpaid is where dunning ends. Stripe still creates invoices but closes them without attempting payment, so the balance owed grows and nothing collects it.
Paused subscriptions never resume and never invoice again
A trial that ends with no card can park the subscription in paused. Stripe stops creating invoices and there is no timeout: it waits for a resume nobody makes.
Pause_collection with no resumes_at silently bills nothing
A support grace period sets pause_collection and never sets resumes_at. The subscription still reads active, and no money has arrived from it since.
Active subscriptions already committed to cancel at period end
cancel_at_period_end leaves the status active until the renewal date, so committed churn is invisible to every dashboard built on subscription status.
Connect_reserved grows as connected accounts go negative
The platform's available balance is short of the books and the gap widens monthly. Stripe is reserving against connected accounts that went negative.
A second-currency balance bucket can never be paid out
The Stripe total never matches the bank, and the gap is a fixed amount in a currency you barely trade in. No payout will ever drain it.
The platform collects zero application fees on its charges
Marketplace volume climbs while platform revenue stays at zero. No ApplicationFee object exists, because application_fee_amount was never passed.
Payouts cannot be tied back to their balance transactions
Finance gets one bank deposit and cannot say what is in it. balance_transactions?payout=po_x returns nothing, because manual payouts are never reconciled.
Charges have a null payment_intent, which means the legacy Charges API
European decline rates run above the account average and 3D Secure never appears. The charges were made by an API call that cannot ask for it.
Legacy card sources still live under customer.sources
Some customers charge fine and others fail with no active card. Two parallel card stores exist on the same account and each code path can see one.
Manual-capture holds expire before anyone captures them
The authorization is valid for days, not weeks, and the clock is the network's. Capture late and the hold drops off the card and the money is gone.
Bank-debit intents stay in processing for over a week
ACH and SEPA payments legitimately sit in processing for days. Code that only ever looks for succeeded turns that state into a permanent one.
A live webhook endpoint points at a dev tunnel or http
It worked for one afternoon. The live endpoint URL is an ngrok hostname that stopped resolving, a localhost, or a plain http:// address.
Event types are firing that no endpoint subscribes to
enabled_events is an allowlist and it drifts. Types generated by products you enabled later are visible in the API and delivered to nobody.
The endpoint listens for charge.succeeded, not payment_intent
Fulfilment runs on a Charge with empty metadata and no customer, so nothing maps back to a cart. The subscription is one integration era behind.
No endpoint subscribes to any payment failure event
The success path is wired perfectly and failures are a black hole: carts stay in processing, dunning runs unseen, delinquent subscribers keep access.
Guest checkouts finish with customer null and can't be linked
customer_creation defaults to if_required, so payment-mode Sessions complete with customer null and the email stays a string on the Session.
Expired Checkout Sessions are never recovered by email
Recovery is opt-in per session. Without after_expiration[recovery], the expired event carries no recovery URL, so there is nothing to send anyone.
Embedded Checkout never redirects and return_url is null
A customer authenticates at their bank and comes back to nowhere. And redirect_on_completion never quietly removes iDEAL from the form entirely.
Payment Link ends on Stripe's page, so fulfilment never fires
after_completion defaults to hosted_confirmation, so the buyer never reaches your server. With no checkout.session.completed webhook, nothing fulfils.
Customers have no address, so tax and SCA exemptions fail
Stripe Tax refuses to finalize with customer_tax_location_invalid, AVS never runs, and European authorisation rates lag. customer.address is null.
SetupIntents use on_session but you bill off-session
Cards saved through the save-for-later flow work at checkout and every unattended renewal dies on authentication_required. usage was set to on_session.
PaymentIntents have a null customer, so payments are orphaned
The Dashboard lists payments with nobody attached. The card cannot be saved, Radar loses its history, and returning buyers pay every time as strangers.
Save_default_payment_method off orphans the card after payment
The first invoice pays and every renewal fails. The card that just worked was never promoted to the subscription's default payment method.
A Person's currently_due blocks the whole account
Every field on the account object is filled in and charges_enabled is still false. The missing paperwork belongs to a director, on an object you never read.
Future_requirements will revoke a capability on a date
Verified accounts that process fine today all break on the same morning. The warning was in a hash your monitor does not read, with a deadline attached.
Card_payments inactive disables transfers as well
You satisfy every field the transfers capability lists and it stays inactive. The blocking requirement belongs to a capability you do not even use.
No external account can settle the account's currency
A payout fails saying there is no external account in that currency, on an account that plainly has a bank account attached.
Endpoints render events at different pinned API versions
One endpoint reads invoice.subscription, the other reads invoice.parent, and only one of them crashes. A migration that started and never finished.
Account default API version is years behind the current one
Documented parameters come back as no such parameter, and Stripe-generated events arrive in an old shape. No endpoint returns the account default.
Recent events carry two different api_version values
A handler that parsed fine all week starts throwing at one timestamp, and replaying an older event through the same code succeeds. The stream has a boundary.
Reused idempotency keys hit 409 idempotency_key_in_use
Checkout fails for a slice of users under load with a 409, or duplicates appear a day later. The same key is on more than one request id.
A report run fails after the 200 and the CSV never lands
Creating a report run returns 200 with status pending. The failure happens later, and nothing subscribes to reporting.report_run.failed, so no file lands.
Report runs past data_available_end return short data
Asking for an interval Stripe has not finalized does not error. The run succeeds with less data than you asked for, so the nightly export short-changes itself.
Sigma scheduled query runs time out and email nothing
The recurring Sigma email finance relies on stops arriving. Runs are ending in timed_out, and no email looks exactly like a quiet week.
Terminal readers sit offline and take no payments
A location's card volume drops to zero and there is nothing to investigate, because no PaymentIntent was ever created. The reader is offline or stale.
Inquiries sit unanswered and escalate into chargebacks
Dispute sweeps filter on needs_response and never see the warning_ family. An inquiry answered in time never becomes a chargeback at all.
Dispute activity is above the 0.75% excessive threshold
No single dispute looks alarming, but the ratio does. Count disputes and early fraud warnings against successful charges before a network does it for you.
Actionable early fraud warnings were never refunded
The issuer has told you a charge is fraud and the money is still yours to give back. Join actionable EFWs to their charges and find the ones untouched.
Elevated-risk card charges are captured with no 3DS
Radar scored the payment risky and let it through unauthenticated. With three_d_secure null there is no liability shift, so every fraud dispute is yours.
Invoiced subscriptions with no days_until_due never age
days_until_due is what puts a due_date on a send_invoice bill. Leave it null and the invoice can never be overdue, so no reminder ever fires.
Draft invoices blocked on customer_tax_location_invalid
Stripe Tax will not finalize an invoice for a customer whose location it cannot resolve. The invoice stays draft, the subscription stays active, nothing errors.
Automatic_tax reports requires_location_inputs on live bills
Stripe Tax is on and most invoices are fine, but a slice of them report requires_location_inputs or failed and have already been billed untaxed.
EU business invoices with no VAT number miss reverse charge
Stripe applies reverse charge from the tax ID on the invoice. With no ID, a business buyer is treated as a consumer and charged local VAT it should not pay.
These are the ones I keep hitting. If yours is broken in a way none of them describes, tell me on LinkedIn — it is usually how the next note gets written.