Skip to content

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.

Read-only keyPython and Node.jsTests included
Browse all 114 scripts on GitHub Download them all as a zip Field guide PDF (114 fixes, 189 KB) Follow @allanninal Every fix on this page has a tested Python and Node.js script in the repo. Free, and MIT as stated in its README.
Why these scripts never write

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

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

StripeDiagnostic

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.

Something not covered here?

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.