Reconciliation August 2026 17 min read

Why bank reconciliations fail

Most people treat a reconciliation difference as a mystery to be solved by re-reading everything. It is not a mystery. It is evidence, and it has a shape. A difference divisible by nine is a transposed number. A difference that is exactly twice an amount is a sign on the wrong side. The same difference every month is not this month's problem at all. Here are the six causes and how to tell them apart in about four minutes.

FlowParse
flowparse.io

The difference is evidence, not noise

When a reconciliation does not balance, the usual response is to start at the top and read down, comparing rows until something looks wrong. On a two-hundred-row account that is an afternoon, and it fails often, because the eye stops seeing after about forty lines.

There is a much better first move, and it takes a calculator. The size of the difference is not arbitrary — it is produced by whatever went wrong, and different failures produce differences with different mathematical properties. A missing row produces a difference equal to that row. A sign error produces double. A swapped pair of digits produces a multiple of nine, always, without exception.

So before reading a single transaction, interrogate the number itself. Four divisions and one search will identify the cause in the large majority of cases, and will tell you which rows to look at rather than sending you through all of them. This article walks through each fingerprint, why the arithmetic works, and the order to test in.

One assumption up front

This all assumes the statement you are reconciling against is itself complete. If rows were lost while converting a PDF, you are debugging two problems at once, which is miserable. Establish that the document is whole first — the two checks below do exactly that.

The order to test in

Run the cheap, decisive tests first. Each one either identifies the cause or eliminates an entire family of causes, and none of them requires reading the ledger line by line.

One: is the difference the same as last period? Two: does it equal an amount on the statement exactly? Three: is half of it an amount you recognise? Four: is it divisible by nine? Five: does it equal the sum of several consecutive rows?

That sequence is not arbitrary either. Test one tells you the problem is not in this period at all, which saves you from searching a month that contains nothing wrong. Tests two through four each cost a single operation. Test five is the most work, so it goes last.

FlowParse
flowparse.io

The same number every month: the opening balance

If the difference is identical this month and last month — not similar, identical — then nothing in either month caused it. A recurring, unchanging difference is a fixed offset, and a fixed offset comes from the point where the account began.

The two usual origins are a wrong opening balance when the account was first set up in the ledger, and an adjustment posted directly against the balance without a corresponding transaction. Both create a permanent gap that every subsequent period inherits, and neither will ever be found by examining this month's activity.

This one is worth checking first precisely because it is invisible to every other technique. People search for it for months. The correct fix is at the source: correct the opening balance, or post the missing entry with a proper date and explanation. Posting a plug every period to make the current month balance simply guarantees the same work forever.

The tell you will miss

A difference that grows by the same amount each period is a different animal: something recurring is being missed every month — a monthly fee, a standing order, a subscription. Constant means opening balance; constant growth means a recurring item.

Equal to one amount: a row missing or a row twice

If the difference matches a single transaction on the statement exactly, that transaction is the story. There are only two possibilities, and a search of the ledger distinguishes them immediately.

No match in the ledger means the row was never entered. Two matches means it was entered twice. The second case has become far more common than it used to be, because it is what a re-run import produces: a load fails halfway, someone runs it again, and the first half now exists in duplicate.

Duplicates are worth a moment of respect. They are the failure most likely to survive review, because every individual row in a duplicated pair looks perfectly legitimate — correct date, correct amount, correct description. Nothing about either row is wrong. Only their coexistence is. That is why deduplication has to be a deliberate check rather than something you hope a reader notices.

FlowParse
flowparse.io

Exactly twice an amount: a sign on the wrong side

Halve the difference. If the result is an amount you recognise from the statement, you have found a classification of direction — a receipt recorded as a payment, a credit recorded as a debit, money in booked as money out.

The doubling is not a coincidence, and understanding why makes the test memorable. A receipt of 2,400 entered as a payment is wrong twice: the 2,400 that should have increased the balance is absent, and a 2,400 that should not exist is decreasing it. The gap between where the balance is and where it should be is therefore 4,800 — two times the amount, never one.

This makes sign errors unusually easy to find once you know the trick, and it is one of the more common failures in practice because it survives casual review so well. The amount is right. The date is right. The description is right. Only the direction is wrong, and direction is the one attribute the eye does not naturally audit.

The same error in extraction

A minus sign lost while reading a PDF produces exactly the same double-sized difference. Parentheses used for negatives, a minus printed after the number instead of before it, or a separate credit column collapsed into one — all produce a sign that was right on paper and wrong in the spreadsheet.

Divisible by nine: a transposition or a slipped decimal

This is the oldest trick in bookkeeping and still the most useful. If the difference divides evenly by nine, you are almost certainly looking at two digits that swapped places, or a decimal point that moved one position.

The reason is straightforward. Swapping two digits changes a number by the difference between those digits multiplied by the difference between their place values — and the gap between any two powers of ten (90, 900, 9,900) is always a multiple of nine. Write 5,841 where you meant 5,481 and you are out by 360, which is 9 × 40. It cannot come out any other way.

A slipped decimal behaves the same way for the same underlying reason. Record 123.45 where the true figure was 1,234.50 and you are short by 1,111.05 — nine tenths of the original, and therefore divisible by nine as well.

To tell the two apart, divide the difference by 0.9. If the answer is an amount that actually appears on the statement, it is a decimal shift and you have just identified the exact row. If it is not, divide by nine instead: the result is the digit gap times the place value, which tells you roughly how large the affected number is and narrows the candidates to a handful.

What you seeThe arithmeticWhat it means
Difference 360360 ÷ 9 = 40Two digits swapped, gap of 4 in the tens/hundreds range
Difference 1,111.05÷ 0.9 = 1,234.50Decimal moved one place on a 1,234.50 row
Difference 9÷ 9 = 1Adjacent digits differing by one — the smallest possible transposition
Difference 4,500÷ 9 = 500Larger place values involved; look at four-figure amounts
FlowParse
flowparse.io

A run of consecutive rows: the page boundary

If none of the single-row tests fits, the difference may be the sum of several rows rather than one. Adding consecutive transactions and comparing running subtotals to the difference sounds tedious, but you do not need to try every combination — consecutive losses are not random, and they cluster in one place.

They cluster at page boundaries. The last rows of a page and the first rows of the next are the ones that go missing when a document is read imperfectly, when a copy-and-paste captures only what was visible, or when a header repeated at the top of each page is mistaken for the start of the data.

So look at the page breaks first. Count the rows on each page of the original and compare with what arrived. A page that lost its first three rows is far more common than three unrelated rows going missing from three unrelated places, and it is much faster to confirm.

This is also the failure that most deserves an automated check rather than human attention, because there is nothing about the surviving data that looks wrong. We wrote about how we hunted this class of loss in our own extraction in eliminating row loss in PDF extraction.

FlowParse
flowparse.io

The fingerprint table

The whole diagnostic on one page. Work down it in order; each row is a single operation.

Property of the differenceMost likely causeHow to confirm
Identical to last periodWrong opening balance or a direct balance adjustmentCompare three periods; if unchanged, go to setup
Grows by the same amount each periodA recurring item never enteredLook for a fee, standing order or subscription
Equals one transaction exactlyThat row is missing or duplicatedSearch the ledger for the amount: nil hits or two
Exactly twice a transactionAmount on the wrong sideHalve it, find that amount, check its direction
Divisible by nineTransposed digits or a slipped decimalDivide by 0.9; if that amount exists, decimal shift
Equals a sum of consecutive rowsRows lost at a page boundaryCount rows per page against the original
Small and irregularRounding or currency conversionVerify against the rate used, then post deliberately
Fits nothing aboveTwo errors cancelling, or a genuine bank errorReconcile in halves to isolate; then query the bank

Two checks, two different blind spots

Before any of this helps, the statement itself has to be complete. There are two independent ways to test that, and the important point is that neither one covers for the other.

The balance chain.Most statements print a running balance on each row. Take any row's balance, subtract the previous row's, and the result should equal that row's amount. Run it down the whole statement and a single misread number lights up immediately, on the exact row.

Its blind spot is severe: if a row vanishes entirely, the chain closes over the gap. The row before and the row after still agree with each other perfectly, because the arithmetic no longer knows anything is meant to sit between them. A statement can pass the chain check while missing a dozen transactions.

The totals identity. Opening balance plus the sum of every transaction should equal the printed closing balance. This one catches exactly what the chain misses, because a dropped row leaves the sum short. It is a statement about the document as a whole rather than about any row.

Its own blind spot is compensating errors: two mistakes of equal size in opposite directions leave the total untouched. So run both. Together they are strong; individually each has a hole large enough to lose a month through.

CheckCatchesBlind toNeeds
Balance chain (row to row)A misread amount on a row that carries a balanceRows dropped entirely — the chain just closes upA printed running balance column
Totals identity (opening + Σ = closing)Dropped rows, missing pages, short importsTwo errors that cancel each other outPrinted opening and closing balances
Both togetherNearly every mechanical failureCorrect amounts posted to the wrong categoryA single-account statement
FlowParse
flowparse.io

When the identity cannot be run at all

Some documents will not support the totals check, and knowing which ones matters more than it sounds. The commonest case is a statement covering several accounts under a single header — a current account, a savings account and a card, each with its own running balance, all printed in one document with one opening and one closing figure at the top.

One opening and closing pair cannot span several chains. Summing every transaction in the document and comparing to that pair produces a number with no meaning, and the honest answer is that the identity could not be evaluated — not a green tick.

We take that seriously in our own product: when a document has more than one account, the totals check stands down and says so, rather than displaying a confirmation it cannot support. A check that reports success when it did not actually run is worse than no check, because it converts uncertainty into false confidence.

The practical response is to split the document by account and run the identity on each chain separately. That usually restores the check completely, and it is also what you need for the ledger anyway.

Accuracy, honestly

We will not promise you 99 % — we will show you which rows to check

Every converter in this market advertises a number: 99 %, 99.5 %, 99.8 %. None of them publishes how it was measured or on which documents — and none of them can tell you which rows fall in the remainder. That is the part you find out later, when two amounts have been glued into one, a column has slid one place to the left, and a reconciliation will not close.

Our extraction is strong. It is also not magic — and neither is anyone else’s.

Reading a PDF is not a solved problem. A layout nobody has seen before, a faded thermal receipt, a bank that marks credits in its own way — each of those can produce a row that looks perfectly ordinary and is wrong. We build hard against that, and we still refuse to sell you a number, because the number is not the thing that protects you. Knowing exactly where to look is.

What actually goes wrong when a PDF is read

These are not hypotheticals. Every one of them is a defect we have found in real documents, reproduced, and built a check for — which is precisely why we can now point at them instead of averaging them into a percentage.

The defectWhat you see in the exportWhat it costs
Two amounts glued into oneOne plausible-looking figure instead of two rowsA total that is short by a whole transaction
A column slides one placeDates in the description, amounts in the balanceEvery row after it is wrong, and none looks wrong
A reference number read as the amount“Payment 910015” booked as 831.00A five-figure hole on a long statement
A credit sign droppedAn expense recorded as incomeThe error is twice the amount, in the wrong direction
A summary box counted as bookings“Previous balance / New balance” added as rowsTotals inflated by exactly the closing balance, twice
A page silently skippedA month that is simply shorterNothing to see — that is what makes it the worst one

So we built the layer that catches them

A second engine, deterministic — ours, and it runs on every document

After the AI reads the document, a separate layer re-does the document’s own arithmetic. Opening balance plus every transaction must equal the closing balance the bank printed. Each row’s running balance must follow from the one above it. Line items must sum to the invoice total. No AI, no confidence score, no guessing — these are proofs, and a document that fails one is provably misread.

It names the rows, not a percentage

When a check fails you do not get a lower score. You get row 48, row 133, row 1 902 — highlighted in place, red where a check proved the reading wrong and amber where it could not confirm it, with the column the check named brighter still. Open the Rows or JSON view, fix those, export. That is the whole loop, and it usually takes under a minute.

The document is the judge, not us

A bank statement carries its own proof: it can catch an error with no human, no reference data and no opinion from us. That is why we lead with it. Where a document genuinely cannot check itself — no running balance, no printed total — we say so, plainly, instead of letting silence imply that everything is fine.

Why the percentage is the wrong number to buy on

Statement sizeWhat “99 % accurate” quietly allowsWhat that means for you
300 rows3 wrong rowsAn afternoon — if you find them
1 200 rows12 wrong rowsA reconciliation that will not close
3 400 rows34 wrong rowsA six-figure error, in cases we have seen

Money work rewards being picky

Please read the flagged rows before you export. That is not a disclaimer — it is the one step that turns a good extraction into a correct one, and we have spent our engineering effort on making it short and precisely targeted rather than on rounding a number up. Anyone can print 99 %. Telling you exactly where the other 1 % is, is the harder promise, and it is the one we are willing to make.

Genuine reconciling items are not failures

A share of every difference is not an error at all, and treating legitimate timing items as mistakes wastes a great deal of time. A cheque written on the 30th and presented on the 3rd is correctly in your books and correctly absent from the statement. Both records are right; they describe different moments.

The same applies to deposits in transit, card payments authorised but not yet settled, and transfers that cross a period end. These get listed as reconciling items, carried forward, and cleared next period when they land. They are not corrected, because there is nothing to correct.

The discipline that matters is aging them. A timing item that is still outstanding two periods later has stopped being a timing item and has become something else — a cheque that was never presented, a transfer that failed silently, or an entry that should never have existed. Any reconciling item older than about sixty days deserves an explanation rather than another carry-forward.

FlowParse
flowparse.io

When nothing fits: compensating errors

Occasionally the difference matches none of the fingerprints. Usually that means there is more than one error, and their interaction has produced a number that reflects neither of them cleanly.

The technique here is bisection, and it is far more efficient than reading. Reconcile the first half of the period on its own. If that half balances, both errors are in the second half; if it does not, you now have a smaller difference to fingerprint, which often becomes recognisable once it is separated from the other one. Repeat. Each cut halves the search space, so even a three-hundred-row month resolves in about eight steps.

The worst version is two errors of identical size on opposite sides, which cancel completely and leave no difference at all. That is not a reconciliation failure — it is a reconciliation that passes while being wrong, and no amount of balancing will surface it. It is caught by review of the individual entries, or not at all, which is the subject of what "reconciled" actually proves.

A worked example

A month closes with the ledger 4,806.00 below the bank. Rather than reading two hundred rows, run the tests.

Last month reconciled cleanly, so it is not an opening-balance offset. No transaction equals 4,806.00, so it is not one missing row. Halving gives 2,403.00 — no such transaction either. Dividing by nine gives 534.00, which is not obviously useful. Dividing by 0.9 gives 5,340.00, which is not on the statement.

Nothing fits, which itself is information: suspect two errors. Bisect. The first fortnight reconciles to a difference of 4,800.00 — and half of that is 2,400.00, which is a customer receipt sitting in the ledger as a payment. One sign error, found.

That leaves 6.00 in the second fortnight, which divides by nine to give 0.67 — not clean. But it also equals 6.00 exactly, and a search finds a bank fee of 6.00 never entered. Two causes, both identified, without reading a single row that was not implicated.

StepTestResult
1Same as last period?No — last month reconciled
2Equals a transaction?No match for 4,806.00
3Halve it: 2,403.00No match — suspect more than one error
4Bisect: first fortnightDifference of 4,800.00
5Halve it: 2,400.00Receipt booked as a payment — found
6Remainder: 6.00Unentered bank fee — found

Preventing the recurrence

Finding the difference is the immediate job. Not finding it again next month is the valuable one, and it costs almost nothing: write down which of the six causes it was, in one line, every time.

After three or four months the log stops being a record and becomes a diagnosis of your process. Transpositions clustering in one account means somebody is typing where they should be importing. Duplicates recurring means an import has no idempotency and someone re-runs it after failures. A constant difference means a setup problem nobody ever went back to.

Each of those has a fix at the process level that costs one afternoon and removes the failure permanently. Without the log you keep solving instances of a problem you have not identified — which is, in practice, why the same difference is found twelve times a year in a great many organisations.

Recurring causeWhat it says about the processThe fix
TranspositionsAmounts are being typed by handImport instead of key; keying is where digits swap
DuplicatesAn import can be run twice with no protectionDeduplicate on a stable transaction identifier
Missing rows in blocksA document is being read or pasted incompletelyRun the totals identity before reconciling
Sign errorsCredit and debit columns are ambiguous somewhereFix the column mapping, not the individual entries
Constant differenceSetup was never correctedRepair the opening balance at source, once
Late timing itemsReconciling items are not being agedReview anything outstanding beyond sixty days
FlowParse
flowparse.io

At volume, the economics change

Every technique here gets more valuable as the row count rises, because reading does not scale and arithmetic does. Searching two hundred rows by eye is unpleasant; searching two thousand is not realistic, and a firm handling many clients is working at the second scale routinely.

Two habits do most of the work. First, run the completeness identity on every statement at the point of conversion, before it reaches anyone's ledger — that removes the entire class of "the data was wrong before I started". Second, reconcile more often on high-volume accounts. The cost of a search grows with the candidate set, so weekly reconciliation on a busy account is genuinely cheaper in total time than monthly, even though it happens four times as often.

For the mechanics of handling a large estate of statements, we covered the workflow separately in processing bank statements at scale and in consolidating a year of statements.

FlowParse
flowparse.io

Common mistakes when hunting a difference

Reading before calculating. The single most expensive habit. Four divisions take a minute and usually name the cause; reading two hundred rows takes an afternoon and often does not.

Posting a plug. An adjustment that makes the difference disappear without explaining it does not close the issue — it hides it, and it hides every future difference inside the same account. If a small amount genuinely cannot be found, write it off deliberately, with a reason and a date.

Carrying it forward. A difference that survives one period becomes invisible by the third. People stop looking at a number they have seen before, and the next problem then hides inside it.

Assuming the bank is right. Usually it is, but not always. Duplicated charges and fees applied twice do happen, and reconciliation exists precisely to catch them. If every internal cause is genuinely eliminated, the statement is a legitimate suspect.

Fixing the entry and not the cause.Correcting today's transposition without asking why an amount was being typed guarantees you will correct another one next month.

Key takeaways

A difference is evidence with a measurable shape, and interrogating the number beats reading the ledger almost every time. The same amount every period means the opening balance. Equal to a transaction means missing or duplicated. Twice a transaction means a sign on the wrong side. Divisible by nine means digits swapped or a decimal moved.

Establish that the statement is complete before you reconcile against it, using both the balance chain and the totals identity — their blind spots are in different places, so neither substitutes for the other. And when a document covers several accounts, accept that the identity cannot run rather than accepting a tick that means nothing.

Finally, log the cause every month. The list of causes is short and repetitive, and after a few months it stops describing incidents and starts describing your process — at which point the fix moves from finding differences to not producing them.

Frequently asked questions

Start from a statement you know is complete

Every statement we convert is checked against its own arithmetic: opening balance plus every transaction against the printed closing balance. If it does not hold, you get the gap and the rows worth examining — before any of it reaches your ledger.

FlowParse
flowparse.io

Related reading