Skip to content

bug: ledger-to-Stripe reconciliation always reports false discrepancies #88

Closed

Description

@JonasBaeumer

Summary

The reconciliation feature introduced in #86 has several bugs that make it unreliable in production.

Bugs

1. Stripe transaction amounts are negative — comparison always fails

src/payments/providers/stripe/reconciliationService.ts:28

Stripe Issuing returns amount as a negative value for captures (e.g. a €35 charge = amount: -3500). The code sums these directly and compares to the positive settledAmount, so every reconciliation run reports a discrepancy even when books are correct.

// Bug: totalCaptured is negative
const totalCaptured = txList.data.reduce((sum, t) => sum + t.amount, 0);
// Fix:
const totalCaptured = txList.data.reduce((sum, t) => sum + Math.abs(t.amount), 0);

2. Missing card record reported as inSync: true

reconciliationService.ts:17-18

When no virtualCard row exists for an intent, the function returns { inSync: true, stripe: null }. A missing DB record could itself be the discrepancy (Stripe has a card, our DB doesn't). This is a false clean signal.

3. Refund transactions excluded from total

reconciliationService.ts:23-26

stripe.issuing.transactions.list({ type: 'capture' }) filters out refund/reversal transactions. If a merchant issues a partial refund, totalCaptured is overstated and a false discrepancy is reported.

4. Stripe API calls have no error handling

reconciliationService.ts:21-26

Both stripe.issuing.cards.retrieve and stripe.issuing.transactions.list are called with no try/catch. A Stripe 404 or 429 causes an unhandled exception that propagates to the webhook handler's outer catch, silently dropping the reconciliation with no audit trace.

5. Transaction list not paginated

reconciliationService.ts:23

transactions.list returns max 100 results by default. High-volume intents could have totalCaptured understated, triggering false discrepancies.

Impact

Reconciliation is effectively broken — it will report discrepancies on every settled intent with real Stripe transactions.

Activity

  1. added a commit that references this issue on May 3, 2026
  2. added a commit that references this issue on May 12, 2026
    b30a7f8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions