Summary
On a party ledger denominated in a foreign currency, CLOSINGBALANCE reads 0.00 while that party's
bill reports the full base-currency amount. Bridge computes the on-account residual as
CLOSINGBALANCE - sum(BILLCL), so it emits a residual equal to the entire outstanding with the
sign reversed — money that does not exist, on a document a CA sends to a client.
Measured 2026-08-23 on licensed TallyPrime Silver against a purpose-built book.
Reproduction
BRIDGE CORPUS FOREX, base currency INR. A $ currency master created over XML, then a party ledger
created with <CURRENCYNAME>$</CURRENCYNAME> — which Tally honours (readback shows currency='$'
where INR ledgers show 'I₹'). One Sales voucher for $1,000 at 83.50 = ₹83,500.
| read |
value |
FX Sales CLOSINGBALANCE |
115000.00 — includes the ₹83,500, so the voucher posted |
Bills Receivable FXU-INV-001 BILLCL |
-83500.00 |
FX USD Debtor 01 CLOSINGBALANCE |
0.00 |
residual = CLOSINGBALANCE - sum(BILLCL) = 0.00 - (-83500.00) = +83500.00
Positive, where the real exposure is negative, and equal in magnitude to the whole receivable.
Why it is reachable
Bridge sends currency_assertion: "INR" on outstandings requests, and nothing has ever tested a
non-INR book against that path because no non-INR book existed. Bridge is read-only, so the
import-side behaviour below is not reachable in production — but this one is. It needs only a
customer with a single foreign-currency debtor.
The residual is not a corner case either. On the one real book measured, ~98.4% of the party balance
sat as unnamed On Account residual; it is the dominant number in an outstandings report.
Root cause, and one honest uncertainty
The leading explanation is that CLOSINGBALANCE on a foreign-currency ledger is expressed in the
ledger's own currency, while BILLCL is in base currency — so the subtraction crosses currencies.
That is not proven, because it was not possible to post a genuine forex amount to test it:
Tally silently discards FOREIGNAMOUNT and RATEOFEXCHANGE on import (CREATED=1 ERRORS=0 EXCEPTIONS=0, both fields absent on readback), so the voucher posts as a plain base-currency entry
against a foreign-denominated ledger.
What is certain is the observable disagreement between the two reads for the same party.
Suggested direction
The first requirement is to refuse rather than misreport, not to support multi-currency:
- detect a party ledger whose
CURRENCYNAME differs from the company base currency
- withhold the report, or mark it partial with a specific reason, rather than emitting a residual
computed across mismatched currencies
CURRENCYNAME is fetchable on the ordinary ledger collection, so detection is cheap and needs no
new request shape
This is the same principle the crosscheck work on #168 settled on: absence of contradiction is not
evidence, and a number that cannot be shown correct should not be published as complete.
Summary
On a party ledger denominated in a foreign currency,
CLOSINGBALANCEreads0.00while that party'sbill reports the full base-currency amount. Bridge computes the on-account residual as
CLOSINGBALANCE - sum(BILLCL), so it emits a residual equal to the entire outstanding with thesign reversed — money that does not exist, on a document a CA sends to a client.
Measured 2026-08-23 on licensed TallyPrime Silver against a purpose-built book.
Reproduction
BRIDGE CORPUS FOREX, base currency INR. A$currency master created over XML, then a party ledgercreated with
<CURRENCYNAME>$</CURRENCYNAME>— which Tally honours (readback showscurrency='$'where INR ledgers show
'I₹'). One Sales voucher for $1,000 at 83.50 = ₹83,500.FX SalesCLOSINGBALANCE115000.00— includes the ₹83,500, so the voucher postedFXU-INV-001BILLCL-83500.00FX USD Debtor 01CLOSINGBALANCE0.00Positive, where the real exposure is negative, and equal in magnitude to the whole receivable.
Why it is reachable
Bridge sends
currency_assertion: "INR"on outstandings requests, and nothing has ever tested anon-INR book against that path because no non-INR book existed. Bridge is read-only, so the
import-side behaviour below is not reachable in production — but this one is. It needs only a
customer with a single foreign-currency debtor.
The residual is not a corner case either. On the one real book measured, ~98.4% of the party balance
sat as unnamed
On Accountresidual; it is the dominant number in an outstandings report.Root cause, and one honest uncertainty
The leading explanation is that
CLOSINGBALANCEon a foreign-currency ledger is expressed in theledger's own currency, while
BILLCLis in base currency — so the subtraction crosses currencies.That is not proven, because it was not possible to post a genuine forex amount to test it:
Tally silently discards
FOREIGNAMOUNTandRATEOFEXCHANGEon import (CREATED=1 ERRORS=0 EXCEPTIONS=0, both fields absent on readback), so the voucher posts as a plain base-currency entryagainst a foreign-denominated ledger.
What is certain is the observable disagreement between the two reads for the same party.
Suggested direction
The first requirement is to refuse rather than misreport, not to support multi-currency:
CURRENCYNAMEdiffers from the company base currencycomputed across mismatched currencies
CURRENCYNAMEis fetchable on the ordinary ledger collection, so detection is cheap and needs nonew request shape
This is the same principle the crosscheck work on #168 settled on: absence of contradiction is not
evidence, and a number that cannot be shown correct should not be published as complete.