May 14, 2026 · 11 min read

Why your bank statement balance doesn't match: 7 specific causes and how to track each one down

When the sum of transactions doesn't equal the printed ending balance, the cause is almost always one of seven specific patterns. A field guide to identifying which one you have, and what to do about each.

A bank statement that doesn't reconcile is one of two things. Either the file is visibly broken (rows missing, columns garbled, dates obviously wrong) and you spot it on first glance, or the spreadsheet looks pristine but the math at the bottom doesn't close. The first kind is annoying. The second kind is dangerous, because it ships through review, gets imported into the books or attached to an underwriting memo, and surfaces three weeks later in a QC pass or a regulator's desk audit when the cost of fixing it is much higher.

The check that catches the second kind is simple: beginning balance plus the signed sum of all transactions should equal the ending balance, within a penny. When it doesn't, the diff (expected minus actual) is the diagnostic signal. The same diff value can come from very different underlying causes, but each cause leaves a specific signature in how the diff relates to the row data. Knowing which signature you're looking at saves you from doing the wrong fix.

Below are the seven causes we see in production traffic, ranked roughly by frequency. The last section is a 60-second triage flow for figuring out which one you have.

1. Sign-flip on a single row

By far the most common cause. Diff equals exactly twice some specific transaction amount. That's the giveaway: a $137.50 charge tagged as a $137.50 deposit moves the running total by $275.00 (the $137.50 you should have subtracted plus the $137.50 you wrongly added).

Why it happens: an LLM or a regex-based parser inferred sign from layout cues that don't hold across all sections of a statement. The classic case is a credit-card statement's "Payments and Credits" section, which structurally resembles a checking-account deposits block but has the opposite economic meaning (a payment reduces your debt, so it's negative on a credit-card ledger). Models that infer "the row sits in a positive-amount column, therefore the amount is positive" will flip the sign on every payment row in the cycle.

How to find it fast: divide the diff by 2; search the row set for that exact amount. If you find one match, that's your sign flip. Fix it, re-run the reconciliation, expect Verified.

2. Missing row at a page break

Diff equals exactly one specific transaction amount, with no doubling. Search the diff value against the printed PDF (not the export) and you'll find a row that exists in the PDF but didn't make it into your spreadsheet.

Why it happens: PDF text extractors process pages independently and re-stitch the output. Rows that land near a page boundary, especially ones whose text wraps across two lines, can get classified as "header" or "footer" on one of the pages and silently dropped. The transaction is still in the visible PDF, just not in the extracted structured data.

How to find it fast: open the PDF side by side with the export. The missing row is almost always at the top of a page (more common) or the very bottom of the previous one. Add it manually, or run the file through a parser that handles page-spanning rows correctly.

3. Display-rounding artefact (the only legitimate mismatch)

Diff is between $0.01 and roughly $0.04, never larger. Row count looks correct, no obvious anomaly anywhere. This one isn't a parser error.

Why it happens: some banks (UK retail names like Lloyds and older HSBC formats, plus a handful of US regional banks) hold sub-cent precision internally for interest accrual. They display each transaction rounded to the cent, but they hold the unrounded version when computing the ending balance. Sum the displayed cents across 200 rows and you can be off the printed ending by one or two cents purely from rounding accumulation. The statement is internally consistent at the level of precision the bank actually uses; the visible numbers just don't add up exactly when re-summed.

How to handle it: accept it. Our reconciliation uses a $0.01 tolerance specifically because of this case. If your diff is one or two cents and nothing else in the file looks suspicious, the file is fine. If you're running a stricter check downstream (a tax-prep workpaper, a QC tie-out), annotate the row.

4. Multi-section layout merged in the wrong order

Diff might be zero, or it might be small. The giveaway here is different: the row count and the total are correct, but the dates in your export jump around instead of moving forward monotonically. Day 5, day 1, day 8, day 2.

Why it happens: Bank of America personal checking statements are the canonical example. The PDF splits transactions across four labelled sections ("Deposits and other additions," "Withdrawals and other subtractions," "Checks," "Service fees") and prints them in that fixed order regardless of when each transaction occurred. A naive parser that walks the PDF top-to-bottom produces a sequence that isn't chronological. The sum still ties to the ending balance, but the per-day running balance reconstruction breaks, your end-of-day reports are wrong, and any downstream filter on a date range pulls the wrong rows.

How to find it fast: sort the export by date and watch for entries that move. If "day 8" rows shift past "day 1" rows on re-sort, the export was definitely not chronologically ordered. Fix it by re-sorting (acceptable for some workflows) or by using a parser that reads the section labels and merges by posting date.

5. Fee or interest posted on a cycle boundary

Diff is small, in the $5 to $50 range, and you can usually find a matching figure on the statement's summary page (a service fee, a wire fee, a small interest credit) that doesn't appear in the transaction table within the period dates.

Why it happens: the statement period closes on day X, but the fee was posted on day X+1 with an effective date inside the period, or vice versa. The bank's summary uses one set of rules for what counts as "inside this period" and the transaction table uses a slightly different one. The discrepancy is real but it's a bookkeeping artefact, not a parser error.

How to find it fast: check the very first and very last rows of the period for posted-vs-effective date disagreements. Cross-reference any fee or interest line on the statement summary that doesn't appear in the row set. The diff usually maps to one specific item.

How to handle it: this isn't a conversion problem. The underlying ledger is correct; the period boundary is just slightly different in two places on the same document. Annotate the export, move on.

6. Combined multi-account or multi-cycle statement (the dual-balance trap)

Diff is large and doesn't match any small set of rows. Often it equals one of the printed sub-balances on the statement (e.g. the savings-account ending balance, or the second cycle's ending balance after a tier change).

Why it happens: the PDF is actually two statements stacked into one document. The bank does this for combined checking + savings products, for accounts that changed tier mid-cycle, or for some business products that bundle multiple sub-accounts. Each sub-statement has its own beginning and ending balance, but a parser that reads the file as a single statement uses the first beginning and the last ending and sums the rows across both. The numbers it's subtracting and the rows it's summing don't describe the same thing.

How to find it fast: count the number of "Beginning Balance" (or equivalent) labels in the PDF. If there's more than one, this is your cause. Sometimes the second balance is hidden inside a sub-section header that doesn't obviously look like a statement boundary.

How to handle it: the PDF needs to be split (or the parser needs to be aware of the structure). Each sub-statement reconciles independently. Chase combined-product statements are a common version of this; our pipeline detects multiple Beginning-Balance markers and treats each block as its own reconciliation pass.

7. Doctored statement (alteration that didn't re-balance)

Clean-looking PDF, no parser error you can find, no page-break issue, no rounding artefact, no multi-section confusion. You've eliminated the other six causes and the math still doesn't close. The PDF itself is internally inconsistent.

Why it happens: someone added or removed transactions from the source PDF without recomputing the totals. This is the most common form of crude statement alteration. Sophisticated alteration also re-computes the running balance and the ending figure, so it doesn't fail this check, but the crude version (which is most of what shows up in opposing-counsel discovery, contested loan files, and embezzlement cases) routinely does.

How to handle it: this isn't a conversion problem. It's an evidentiary signal. The protocol from here is to document the specific row where the balance breaks, request a certified copy from the institution, and treat the discrepancy itself as part of the finding. The full layered detection method is in how forensic accountants detect altered bank statements; the operational side of running this on multi-year discovery packets is on the forensic-accountants page.

60-second triage: which one do I have?

  1. Is the diff under five cents? Probably cause #3, accept it.
  2. Does the diff equal exactly twice the value of any one row? Cause #1 (sign flip on that row).
  3. Does the diff equal exactly one row's value, with no doubling? Cause #2 (missing row at a page break).
  4. Are dates out of chronological order in the export? Cause #4 (multi-section merge).
  5. Does the diff match a fee, interest, or service-charge figure on the statement summary? Cause #5 (cycle-boundary posting).
  6. Does the PDF contain more than one "Beginning Balance" label? Cause #6 (combined statement).
  7. None of the above explains it? Consider cause #7 (alteration). The PDF's own arithmetic is broken.

In production, the breakdown across these seven causes for the conversions that initially fail reconciliation looks roughly like: cause #1 (sign flip) is about half, cause #2 (missing row at page break) is another fifth, cause #3 (rounding) is about a tenth, causes #4 through #6 each show up in low single-digit percentages, and cause #7 (genuine alteration) is the rare one — meaningful when it happens, statistically tiny across the corpus.

Why we wrap every conversion in this check

The reason every export from our pipeline runs the running-balance check, even when the model returns a clean-looking spreadsheet, is exactly this: most of the time the check passes and we ship a Verified file. When it doesn't, the diff itself is a diagnostic. We can route to a corrective LLM retry with the exact diff quoted back to the model, fall back to a flagged Unverified result with the row pointer, or escalate to manual review depending on the cause we infer from the signature. The user gets either a Verified file or a specific honest pointer to where the math broke. They never get a clean-looking spreadsheet that quietly understates income or hides an overdraft cluster.

For the operational pricing and workflow specifics by audience: bookkeepers and accounting firms run this on monthly close on the bookkeepers page; loan officers and underwriters processing applicant bundles use the lenders & underwriters page; family-law and forensic engagements with multi-year discovery packets are on the forensic-accountants page and divorce-attorneys page.

Convert a statement and see the reconciliation result — 15 free pages, no card

Other guides