A newly reported Hyperswitch bug can cause Stripe Connect refunds to be sent against the wrong Stripe account when a key payment record is missing, leaving some successfully completed payments impossible to refund through the normal API path.
The issue was filed in the Hyperswitch GitHub repository at 22:12 UTC on October 1, or 01:12 Cairo time on October 2. The reporter says the problem was discovered on a live merchant using Stripe Connect direct charges and reproduced against Hyperswitch’s current main branch.
The strongest evidence comes from 120 days of merchant refund data. According to the report, 1,330 successful refund attempts covering 1,327 payments all had the relevant payment_attempt.charges field populated. By contrast, all 22 failed refund attempts across six separate payments had that field set to NULL.
Every one of the six affected payments used Affirm, a redirect-based payment method. The reporter says the merchant currently has a four-figure dollar amount that cannot be refunded through the normal Hyperswitch API, with some payments retried as many as six times and failing identically each time.
The issue remains open and labeled as a bug awaiting triage. At the latest check, there were no maintainer comments, assignees or linked pull requests fixing the problem.
A Missing Charge ID Changes Where Hyperswitch Sends the Refund
The failure sits inside the way Hyperswitch reconstructs Stripe Connect refund information.
For Stripe Connect direct charges, the original payment belongs to a connected Stripe account rather than the platform’s own account. A later refund therefore has to be routed back into that same connected-account context.
Hyperswitch normally obtains the Stripe charge ID from stored payment-attempt data. But according to the bug report, when both possible charge-ID fields are unavailable, the function responsible for generating split-refund information returns no split-refund data at all.
That changes two things downstream.
First, Hyperswitch sends a refund using the Stripe PaymentIntent rather than the Stripe charge. More importantly, it no longer adds the Stripe-Account header identifying the connected account.
The request therefore reaches Stripe in the context of the platform account, even though the PaymentIntent exists under the connected account.
Stripe responds with a 404 resource_missing error and the message “No such payment_intent.”
This is not necessarily because the PaymentIntent does not exist. It can exist perfectly normally — just under a different Stripe account from the one Hyperswitch is querying.
The Payment Can Succeed Long Before the Refund Bug Becomes Visible
The more significant part of the report is how charges becomes NULL in the first place.
The reporter describes a path involving redirect-based payment methods such as Affirm. During the initial authorization response, Stripe can return the payment in a requires_action state before a final charge ID is available.
If Hyperswitch later performs a payment-status synchronization with Stripe, the charge can be retrieved and persisted into the payment attempt.
But if the payment reaches its final successful state through a webhook alone, the report says that webhook-driven update does not persist the charge ID into payment_attempt.charges.
The customer’s payment can therefore finish successfully with no visible issue.
Only days or weeks later, when the merchant attempts a refund, does the missing database field become operationally important.
That makes this different from an obvious payment outage. Dave Finances recently examined Xendit payment failures where callbacks and transaction states diverged across different infrastructure layers. In both cases, the customer-facing transaction can tell only part of the story about what has actually been persisted deeper in the payments stack.
Stripe Supports Refunding by PaymentIntent — If the Account Context Is Correct
The report argues that losing the charge ID should not necessarily make these payments impossible to refund.
Stripe’s official refund API documentation says a refund can be created using either a Charge or a PaymentIntent.
That means Hyperswitch could potentially continue using the known PaymentIntent when the charge ID is unavailable, provided it preserves the connected-account routing information and sends the request in the correct Stripe account context.
The bug reporter says Hyperswitch already retains the connected account ID and the fact that the original transaction was a direct charge inside separate split-payment data.
The core problem is therefore not merely “missing charge ID.” It is that the absence of that ID causes other routing information to be silently discarded as well.
At minimum, the reporter argues, Hyperswitch should reject the refund explicitly if it cannot safely construct the correct request rather than quietly converting it into a non-Connect refund that is guaranteed to target the wrong account.
The Six Failed Payments Could Be the Visible Edge of a Larger Historical Problem
The live-merchant data is compelling, but it needs to be interpreted carefully.
A 100% correlation exists inside this specific sample: every successful refund had charges populated, and every resource_missing failure had it missing.
That does not establish that every Hyperswitch merchant using Stripe Connect has the same exposure.
The six affected payments all used Affirm, the dataset comes from one merchant, and the bug report has not yet been publicly validated by Hyperswitch maintainers.
Still, the architecture raises a more interesting question than the six known failures themselves.
If historical Stripe Connect direct-charge payments were completed through webhooks without a later synchronization step, there could potentially be older successful payments carrying the same missing database state. Those payments would appear perfectly healthy until somebody tries to refund them.
That kind of latent operational liability is harder to detect than a conventional outage.
A visible failure produces alerts immediately. A missing piece of payment metadata can remain dormant indefinitely.
The same principle appears elsewhere in financial infrastructure. Dave Finances has covered payment reconciliation problems where different systems disagree about whether a transaction is truly complete. The Hyperswitch case pushes that idea one step further: the payment itself can genuinely be complete while the records needed for a future operation are incomplete.
Why This Matters More Than a Four-Figure Refund Backlog
The immediate monetary impact described in the report is relatively small: a four-figure dollar total across six payments.
That number is probably the least interesting part of the story.
The real issue is whether successful payment processing is creating hidden future refund failures across a larger installed base.
Payment infrastructure depends heavily on state being preserved correctly between processors, orchestration layers, databases, webhooks and merchant systems. The merchant does not care whether an internal field called charges was populated. It cares that a customer who paid successfully can later receive a refund.
This is why middleware defects can be disproportionately important. A platform can sit between two otherwise healthy systems and still create a failure that neither endpoint would produce independently.
That broader dependency problem also appeared in Dave Finances’ coverage of a QuickNode infrastructure incident, where the underlying Solana network remained functional while applications depending on a specific middleware provider experienced failures.
Payments are even less forgiving because the failure may involve real customer money and obligations that appear long after the original transaction.
The Most Important Next Step Is Finding the Same Fingerprint Elsewhere
The strongest way to determine the real scope would be to search other hosted Hyperswitch merchants using Stripe Connect direct charges and redirect-based payment methods for the same fingerprint.
The pattern is unusually specific: successful payment, missing payment_attempt.charges, refund request sent without connected-account routing, followed by Stripe returning resource_missing for a PaymentIntent that exists under another account.
If the same sequence appears across several unrelated merchants, this stops looking like a six-payment edge case and starts looking like a systemic persistence bug.
If it does not, there may be additional configuration or workflow conditions unique to the affected merchant.
The eventual fix also matters. Correcting future refund routing would solve only half the problem if historical webhook-settled payments already contain NULL charge records. Those rows may need a backfill or another recovery process before merchants discover the issue one refund at a time.
That is the uncomfortable part of this bug.
The payment can work. The customer can receive the product. The transaction can sit quietly in a successful state for months.
Then the merchant tries to give the money back — and discovers that the infrastructure forgot just enough information to stop the refund from finding its way home.
As payment providers increasingly build more complex orchestration layers around merchants, something Dave Finances has also examined in merchant payment infrastructure, reliability is increasingly about more than whether the initial transaction succeeds. Every later operation has to inherit the correct account, routing and settlement context too.
Johan Shamshad is a financial markets writer at Dave Finances covering cryptocurrencies, trading platforms, brokers, fintech, financial regulation, and developments across global markets. He previously worked at Gulf News, adding newsroom experience to his coverage of fast-moving financial and digital-asset markets.
His work focuses on identifying market-moving events, company developments, regulatory changes, product launches, and shifts in trading and financial infrastructure.
Johan contributes news and analysis designed to help readers understand not only what happened, but why a development matters and how it may affect the wider financial landscape.

