Incident Post: Quarterly Aggregate Cross-Contamination Fix (v1.0.459)
Incident Post: Quarterly Aggregate Cross-Contamination Fix (v1.0.459)
Released in: v1.0.459
Severity: Critical (data integrity — affects HMRC submissions)
Affected organisations: Those with both a self-employment business and a property business registered under the same organisation
Summary
A bug in the computeBusiness procedure caused quarterly aggregate totals to be computed from all transactions in an organisation, rather than being filtered by the HMRC category type (SE vs. property) appropriate for the business being computed. Since these stored totals are what gets submitted to HMRC via the MTD ITSA API, organisations with both business types could have had incorrect figures filed.
This has been resolved in v1.0.459.
Background
The MTD ITSA platform handles two types of HMRC businesses:
| Business type | HMRC category prefix | Example categories |
|---|---|---|
| Self-employment | se_ | se_turnover, se_office_costs, … |
| Property | (no se_ prefix) | rental_income, property_repairs, … |
When computing a quarterly summary, the platform calls computeAggregates to sum transaction amounts by HMRC category for the relevant period. These aggregated totals are stored and subsequently submitted to HMRC.
The UI's running totals (surfaced via listBusiness) already applied the correct category-prefix filter — SE businesses only see SE-prefixed transactions, property businesses only see non-SE transactions. However, computeBusiness, which produces the stored values that are actually sent to HMRC, did not apply the same filter.
The Bug
For an organisation with both a property business and a self-employment business:
When computing a property quarter:
The aggregate query fetched all org transactions, including those with se_ category prefixes. While sumCategories would return 0 for SE keys (since they don't map to property income/expense columns), the aggregate map was contaminated. Any future normalisation or mapping change could silently inflate property totals submitted to HMRC.
When computing an SE quarter:
The aggregate query fetched all org transactions, including property-categorised ones (rental_income, property_repairs, etc.). Again sumCategories(agg, SE_INCOME_CATS) would yield 0 for those keys, but the aggregate was incorrect and inconsistent with what the UI displayed.
The practical result: for mixed-business organisations, the stored totals submitted to HMRC could diverge from the running totals shown in the UI, with a risk of incorrect values being filed as HMRC normalisation of the category map evolves.
The Fix
The fix introduced an optional categoryFilter parameter to computeAggregates and wires it up in computeBusiness to mirror the filter already in place in listBusiness:
// SE business → only transactions with hmrcCategory LIKE 'se_%'
// Property business → only transactions with hmrcCategory NOT LIKE 'se_%'
const categoryFilter = isSelfEmployment
? sql`${transactions.hmrcCategory} LIKE 'se_%'`
: sql`${transactions.hmrcCategory} NOT LIKE 'se_%'`;
const agg = await computeAggregates(
ctx.orgId,
null, // aggregate across all properties for the business
qRange.from,
qRange.to,
categoryFilter,
);
The computeAggregates function pushes the filter into the SQL WHERE clause alongside the existing conditions:
if (categoryFilter) {
conditions.push(categoryFilter);
}
Additionally, businessType and the effective category filter pattern (se_* or !se_*) are now recorded in the audit log metadata for every computeBusiness invocation, improving traceability.
Who Is Affected
| Organisation type | Impact |
|---|---|
| Property income only | No impact — all transactions already have non-se_ categories; the filter is a no-op |
| Self-employment only | No impact — all transactions already have se_ categories; the filter is a no-op |
| Both property and SE income | Previously affected. Stored aggregates are now correctly scoped per business type |
Recommendations
If your organisation has both a self-employment business and a property business configured, we recommend reviewing any quarterly submissions computed and filed prior to v1.0.459. For quarters that have not yet been formally submitted to HMRC, re-running computeBusiness after upgrading to v1.0.459 will produce corrected stored totals.
Files Changed
src/lib/routers/quarterly-summary.ts—computeAggregatessignature updated;computeBusinessmutation updated with category filter logic and expanded audit log metadata.