You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Expense-Tax rate modified violation appears after merging expenses & disappears on navigation #86306
Version Number: V9.3.42-3 Reproducible in staging?: Yes Reproducible in production?: Yes If this was caught during regression testing, add the test name, ID and link from BrowserStack:#85658 Email or phone of affected tester (no customers):dreamnitethedragon+yydyd373@gmail.com Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Redminote 10S Android 13 App Component: Money Requests
Please re-state the problem that we are trying to solve in this issue.
After merging two expenses with different tax rates, the merged expense shows a "tax rate was modified" violation that disappears on navigation. Additionally, unrelated expenses may also show spurious violations.
What is the root cause of that problem?
There are two bugs in mergeTransactionRequest in MergeTransaction.ts:
Bug 1 — Target transaction violations are duplicated by optimistic data ordering
optimisticTransactionViolations writes violations for BOTH the target and source transactions using Onyx.METHOD.MERGE:
However, the target transaction's violations are already computed by getViolationsOnyxData (called from getUpdateMoneyRequestParams) using Onyx.METHOD.SET:
When API.write calls Onyx.update(), both operations target the same key. Due to Onyx v3's batching, SET enqueues [null, computed] and then MERGE pushes the original violations to the same queue — resulting in [null, computed, original]. When mergeAndMarkChanges processes this queue, it concatenates the arrays, causing duplicate violation entries on the target transaction.
These duplicated violations appear immediately after merge and disappear on the next navigation because the server response overwrites them with the correct violations.
Bug 2 — Source transaction violations are orphaned
The source transaction itself is SET to null (deleted), but its violations are only MERGEd (filtering out DUPLICATED_TRANSACTION) rather than being deleted. This leaves orphaned violation data in ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS for a transaction that no longer exists.
What changes do you think we should make in order to solve the problem?
Remove the target transaction from optimisticTransactionViolations entirely — let getViolationsOnyxData (via getUpdateMoneyRequestParams) handle target violations exclusively with its SET operation, avoiding the SET+MERGE concatenation.
Change the source transaction's violations to use Onyx.METHOD.SET with null value instead of MERGE, properly cleaning up violations for the deleted transaction. Add corresponding failure data that restores the source violations for rollback.
This issue has not been updated in over 15 days. eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!
Activity
Fix duplicate violations on target transaction after merge
wildan-m commentedon Mar 25, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
After merging two expenses with different tax rates, the merged expense shows a "tax rate was modified" violation that disappears on navigation. Additionally, unrelated expenses may also show spurious violations.
What is the root cause of that problem?
There are two bugs in
mergeTransactionRequestinMergeTransaction.ts:Bug 1 — Target transaction violations are duplicated by optimistic data ordering
optimisticTransactionViolationswrites violations for BOTH the target and source transactions usingOnyx.METHOD.MERGE:App/src/libs/actions/MergeTransaction.ts
Lines 517 to 528 in 9ac9e98
However, the target transaction's violations are already computed by
getViolationsOnyxData(called fromgetUpdateMoneyRequestParams) usingOnyx.METHOD.SET:App/src/libs/Violations/ViolationsUtils.ts
Lines 650 to 654 in 9ac9e98
When
API.writecallsOnyx.update(), both operations target the same key. Due to Onyx v3's batching, SET enqueues[null, computed]and then MERGE pushes the original violations to the same queue — resulting in[null, computed, original]. WhenmergeAndMarkChangesprocesses this queue, it concatenates the arrays, causing duplicate violation entries on the target transaction.https://github.com/nickenbach/react-native-onyx/blob/8c0a72f3d27e49daf5a2aaaba1aff0c4cd01c47d/lib/Onyx.ts#L411-L424
These duplicated violations appear immediately after merge and disappear on the next navigation because the server response overwrites them with the correct violations.
Bug 2 — Source transaction violations are orphaned
The source transaction itself is SET to null (deleted), but its violations are only MERGEd (filtering out
DUPLICATED_TRANSACTION) rather than being deleted. This leaves orphaned violation data inONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONSfor a transaction that no longer exists.What changes do you think we should make in order to solve the problem?
Remove the target transaction from
optimisticTransactionViolationsentirely — letgetViolationsOnyxData(viagetUpdateMoneyRequestParams) handle target violations exclusively with its SET operation, avoiding the SET+MERGE concatenation.Change the source transaction's violations to use
Onyx.METHOD.SETwithnullvalue instead of MERGE, properly cleaning up violations for the deleted transaction. Add corresponding failure data that restores the source violations for rollback.Compare: https://github.com/Expensify/App/compare/main...wildan-m:App:wildan/86306-fix-merge-violation-ordering?expand=1
melvin-bot commentedon Mar 30, 2026
Huh... This is 4 days overdue. Who can take care of this?
melvin-bot commentedon Mar 30, 2026
Eep! 4 days overdue now. Issues have feelings too...
melvin-bot commentedon Mar 30, 2026
Huh... This is 4 days overdue. Who can take care of this?
melvin-bot commentedon Apr 1, 2026
Still overdue 6 days?! Let's take care of this!
melvin-bot commentedon Apr 3, 2026
Now this issue is 8 days overdue. Are you sure this should be a Daily? Feel free to change it!
melvin-bot commentedon Apr 7, 2026
12 days overdue now... This issue's end is nigh!
melvin-bot commentedon Apr 10, 2026
This issue has not been updated in over 14 days. eroding to Weekly issue.
melvin-bot commentedon May 7, 2026
This issue has not been updated in over 15 days. eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!
melvin-bot commentedon Jul 20, 2026
@nlemma, this Monthly task hasn't been acted upon in 6 weeks; closing.
If you disagree, feel encouraged to reopen it -- but pick your least important issue to close instead.