TB upload says "not balanced"
The preview after Upload Trial Balance shows an amber badge: "Trial balance is not balanced by SGD {n}".
What this means
After sign normalisation, Σ currentYearBalance ≠ 0 (tolerance: ±1.0 SGD). The handler still imported the rows and the engagement transitioned to TB_UPLOADED, but everything downstream will surface the imbalance until you fix it.
Causes (most common first)
- Subtotal rows in the source file. The parser sums every row; a subtotal row double-counts. Strip them at source.
- Mixed sign conventions across columns. Some clients export "debit positive, credit positive" on different columns; the detector flags the second column but cannot infer intent. Re-export with a single convention.
- Missing rows. The source file was truncated — an opening journal at the end of the file dropped off.
- Currency mix. The TB contains rows in a different currency than
engagement.functionalCurrency. The parser does not convert. Re-export in the functional currency. - Rounding artefacts larger than ±1.0 SGD across many rows. Adjust at source.
Diagnose
sql
SELECT sum(current_year_balance) AS imbalance
FROM fs_trial_balance_items WHERE engagement_id = '<engagementId>';
-- expect ≈ 0; the magnitude tells you which scale of correction is neededIf the imbalance is large (≥ 100 SGD), almost certainly a subtotal row or missing row. If small (1–10 SGD), rounding.
sql
SELECT account_code, account_description, current_year_balance
FROM fs_trial_balance_items
WHERE engagement_id = '<engagementId>'
ORDER BY abs(current_year_balance) DESC LIMIT 20;
-- look for an account that "shouldn't be there" (subtotal row)Fix
- Fix at the source TB.
- Re-upload via the same drag-drop. The engagement returns to
DRAFTthen back toTB_UPLOADED; the priorFsTrialBalanceItemrows are dropped.
Why we don't reject the upload
The pragmatic choice: a 0.50 SGD rounding artefact shouldn't block ingestion. The reviewer's judgement decides whether to ship anyway (document the rationale) or fix.