[GH-ISSUE #7015] [Bug]: SimpleFIN imports cross-account mirror transactions from Mercury Bank #28738

Closed
opened 2026-04-18 05:29:23 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @benton-pgcis on GitHub (Feb 18, 2026).
Original GitHub issue: https://github.com/actualbudget/actual/issues/7015

Verified issue does not already exist?

  • I have searched and found no existing issue
  • I will be providing steps how to reproduce the bug

What happened?

When using SimpleFIN to sync multiple Mercury Bank accounts (Checking, Credit Card, Savings), transactions that belong to one account get imported as phantom mirror entries on the other linked Mercury accounts.

For example, a wire deposit of $3,157 into Checking also appears as:

  • A -$3,157 charge on Credit Card Mercury IO
  • A +$3,157 deposit on Savings

Each mirror transaction has a unique SimpleFIN transaction_id (TRN-...), so Actual's deduplication doesn't catch them. They look like real, distinct transactions.

The mirror transactions have a telltale pattern: the payee name gets prefixed with a single letter corresponding to the originating account:

  • S prefix → appears to reference Savings/wires (e.g., "S Todd Sorrel Wire")
  • M prefix → appears to reference Mercury/ACH (e.g., "M Mach8 ACH Payment")
  • P prefix → appears to reference Payments (e.g., "P PGCIS TEXAS HOLD Request or Invoice Payment")
  • C O prefix → appears to reference Credit/Other (e.g., "C O CAPITAL ONE ACH Pull")

Scope of the problem

In my budget, I found 13 bogus mirror transactions spanning Dec 13 - Dec 26, 2025, across Credit Card and Savings accounts. These were all mirrors of legitimate Checking transactions. The pattern continued into Feb 2026 with new imports.

Example from Dec 19, 2025 (every Checking transaction tripled):

Amount Checking (real) Credit Card Mercury IO (bogus) Savings (bogus)
+$3,157 "Todd Sorrel" "S Todd Sorrel Wire" "S Todd Sorrel Wire"
+$17,209 "PGCIS TEXAS HOLD" "P PGCIS TEXAS HOLD" "P PGCIS TEXAS HOLD"
-$1,047 "Mach8 ACH Payment" "M Mach8 ACH Payment" "M Mach8 ACH Payment"

Where the bug lives

After reviewing the source code (packages/sync-server/src/app-simplefin/app-simplefin.js), I believe the issue is upstream of Actual:

  1. Mercury's bank feed (via MX/Finicity aggregator) reports cross-account "related activity" as if they're real transactions on each account
  2. SimpleFIN returns them with unique trans.id values per account, so they look legitimate
  3. Actual imports them because the transaction ID doesn't already exist — getAccountResponse() trusts that account.transactions only contains transactions for that specific account

The SimpleFIN protocol spec states transactions should be scoped to their parent account, so this appears to be a data quality issue from Mercury's aggregator feed.

Suggested mitigation in Actual

Even though the root cause is upstream, Actual could add a cross-account duplicate detection heuristic during SimpleFIN import:

  • If the same absolute amount appears on the same date across two linked accounts from the same bank
  • AND the payee names are similar (e.g., one is a prefix + substring of the other)
  • Flag or skip the import

Alternatively, a simpler approach: detect the single-letter prefix pattern (S , M , P , C O ) on imported payee names and flag them as potential mirrors.

Steps to reproduce

  1. Link multiple Mercury Bank accounts via SimpleFIN (Checking + Credit Card + Savings)
  2. Wait for a wire, ACH, or other non-card transaction to hit Checking
  3. Sync all accounts
  4. Observe the same transaction mirrored on Credit Card and/or Savings with prefixed payee names

Where are you hosting Actual?

PikaPods

What browsers are you seeing the problem on?

Chrome

Operating System

Mac OSX

Originally created by @benton-pgcis on GitHub (Feb 18, 2026). Original GitHub issue: https://github.com/actualbudget/actual/issues/7015 ### Verified issue does not already exist? - [X] I have searched and found no existing issue - [X] I will be providing steps how to reproduce the bug ### What happened? When using SimpleFIN to sync multiple Mercury Bank accounts (Checking, Credit Card, Savings), **transactions that belong to one account get imported as phantom mirror entries on the other linked Mercury accounts.** For example, a wire deposit of $3,157 into Checking also appears as: - A **-$3,157 charge** on Credit Card Mercury IO - A **+$3,157 deposit** on Savings Each mirror transaction has a unique SimpleFIN `transaction_id` (TRN-...), so Actual's deduplication doesn't catch them. They look like real, distinct transactions. **The mirror transactions have a telltale pattern:** the payee name gets prefixed with a single letter corresponding to the originating account: - `S ` prefix → appears to reference Savings/wires (e.g., "S Todd Sorrel Wire") - `M ` prefix → appears to reference Mercury/ACH (e.g., "M Mach8 ACH Payment") - `P ` prefix → appears to reference Payments (e.g., "P PGCIS TEXAS HOLD Request or Invoice Payment") - `C O ` prefix → appears to reference Credit/Other (e.g., "C O CAPITAL ONE ACH Pull") ### Scope of the problem In my budget, I found **13 bogus mirror transactions** spanning Dec 13 - Dec 26, 2025, across Credit Card and Savings accounts. These were all mirrors of legitimate Checking transactions. The pattern continued into Feb 2026 with new imports. **Example from Dec 19, 2025 (every Checking transaction tripled):** | Amount | Checking (real) | Credit Card Mercury IO (bogus) | Savings (bogus) | |--------|----------------|-------------------------------|-----------------| | +$3,157 | "Todd Sorrel" ✅ | "S Todd Sorrel Wire" ❌ | "S Todd Sorrel Wire" ❌ | | +$17,209 | "PGCIS TEXAS HOLD" ✅ | "P PGCIS TEXAS HOLD" ❌ | "P PGCIS TEXAS HOLD" ❌ | | -$1,047 | "Mach8 ACH Payment" ✅ | "M Mach8 ACH Payment" ❌ | "M Mach8 ACH Payment" ❌ | ### Where the bug lives After reviewing the source code (`packages/sync-server/src/app-simplefin/app-simplefin.js`), I believe the issue is **upstream of Actual**: 1. **Mercury's bank feed** (via MX/Finicity aggregator) reports cross-account "related activity" as if they're real transactions on each account 2. **SimpleFIN** returns them with unique `trans.id` values per account, so they look legitimate 3. **Actual** imports them because the transaction ID doesn't already exist — `getAccountResponse()` trusts that `account.transactions` only contains transactions for that specific account The SimpleFIN protocol spec states transactions should be scoped to their parent account, so this appears to be a data quality issue from Mercury's aggregator feed. ### Suggested mitigation in Actual Even though the root cause is upstream, Actual could add a **cross-account duplicate detection heuristic** during SimpleFIN import: - If the same absolute amount appears on the same date across two linked accounts from the same bank - AND the payee names are similar (e.g., one is a prefix + substring of the other) - Flag or skip the import Alternatively, a simpler approach: detect the single-letter prefix pattern (`S `, `M `, `P `, `C O `) on imported payee names and flag them as potential mirrors. ### Steps to reproduce 1. Link multiple Mercury Bank accounts via SimpleFIN (Checking + Credit Card + Savings) 2. Wait for a wire, ACH, or other non-card transaction to hit Checking 3. Sync all accounts 4. Observe the same transaction mirrored on Credit Card and/or Savings with prefixed payee names ### Where are you hosting Actual? PikaPods ### What browsers are you seeing the problem on? Chrome ### Operating System Mac OSX
Author
Owner

@youngcw commented on GitHub (Feb 18, 2026):

This is very likely an issue for simplefin/MX. You can check by looking at the raw data pulled from simplefin in Actual by opening the browser console (ctrl-shift-I) then syncing.

<!-- gh-comment-id:3923047085 --> @youngcw commented on GitHub (Feb 18, 2026): This is very likely an issue for simplefin/MX. You can check by looking at the raw data pulled from simplefin in Actual by opening the browser console (ctrl-shift-I) then syncing.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#28738