[Bug]: Incorrect transaction matching on import #2847

Open
opened 2026-02-28 20:30:32 -06:00 by GiteaMirror · 4 comments
Owner

Originally created by @hornjbl on GitHub (Jan 21, 2026).

Verified issue does not already exist?

  • I have searched and found no existing issue

What happened?

I have a record imported via ofx file on day 19. The amount is 161.95. I've split the transaction into two, one with a value of 111.95, and the second with a value of 50.00.

On the next day (20), I import a new ofx file. It has that same record in it, but also another (different) transaction with a value of 50.00.

The import process matches that incoming transaction incorrectly to the child (split) record from the previous day, based on the fact that both have an amount value of 50.00.

I would have expected the process to match on the parent (original) transactions, finding one to have a value of 161.95 and the next (incoming one) of 50.00, and NOT find any match against the parent OR the children (splits) of either.

Note:

I tried this on web via pikapod as well as the desktop app, and the issue is on both.

How can we reproduce the issue?

  1. Import Bank_Import 1.csv (using the description field as the note value).
  2. Find the transaction with value -161.95 (PNA CENTURION 4548*6647 16 JAN CHEQUE CARD PURCHASE)
  3. Split the record with amount value -161.95 into two splits, one with 111.95 and another with 50.00
  4. Import Bank_Import 2.csv (containing a transaction with -50.00, ref RUHAN: PURESAVE ACTI BRANCH TRANSACTION)
  5. Check the transaction valued -161.95.
  6. Check the split under that record with value of 50.00. It has matched the imported transaction with value of 50 INCORRECTLY.
  7. Look for a transaction (unsplit) with value of 50.00. You shouldn't be able to find it.

Bank_Import 2.csv
Bank_Import 1.csv

Where are you hosting Actual?

Pikapods

What browsers are you seeing the problem on?

Microsoft Edge

Operating System

Windows 11

Originally created by @hornjbl on GitHub (Jan 21, 2026). ### Verified issue does not already exist? - [x] I have searched and found no existing issue ### What happened? I have a record imported via ofx file on day 19. The amount is 161.95. I've split the transaction into two, one with a value of 111.95, and the second with a value of 50.00. On the next day (20), I import a new ofx file. It has that same record in it, but also another (different) transaction with a value of 50.00. The import process matches that incoming transaction incorrectly to the child (split) record from the previous day, based on the fact that both have an amount value of 50.00. I would have expected the process to match on the parent (original) transactions, finding one to have a value of 161.95 and the next (incoming one) of 50.00, and NOT find any match against the parent OR the children (splits) of either. Note: I tried this on web via pikapod as well as the desktop app, and the issue is on both. ### How can we reproduce the issue? 1. Import Bank_Import 1.csv (using the description field as the note value). 2. Find the transaction with value -161.95 (PNA CENTURION 4548*6647 16 JAN CHEQUE CARD PURCHASE) 3. Split the record with amount value -161.95 into two splits, one with 111.95 and another with 50.00 4. Import Bank_Import 2.csv (containing a transaction with -50.00, ref RUHAN: PURESAVE ACTI BRANCH TRANSACTION) 5. Check the transaction valued -161.95. 6. Check the split under that record with value of 50.00. It has matched the imported transaction with value of 50 INCORRECTLY. 7. Look for a transaction (unsplit) with value of 50.00. You shouldn't be able to find it. [Bank_Import 2.csv](https://github.com/user-attachments/files/24765246/Bank_Import.2.csv) [Bank_Import 1.csv](https://github.com/user-attachments/files/24765247/Bank_Import.1.csv) ### Where are you hosting Actual? Pikapods ### What browsers are you seeing the problem on? Microsoft Edge ### Operating System Windows 11
GiteaMirror added the split transactionsbank synctransactionsbugimporters labels 2026-02-28 20:30:32 -06:00
Author
Owner

@hornjbl commented on GitHub (Jan 21, 2026):

Resultant match in Actual (incorrect):

Image



What this looks like in YNAB (correct):

Image
@hornjbl commented on GitHub (Jan 21, 2026): Resultant match in Actual (incorrect): <img width="1010" height="116" alt="Image" src="https://github.com/user-attachments/assets/357295d9-9790-4e5f-84dc-661bb4fcb42e" /> <br><br> What this looks like in YNAB (correct): <img width="803" height="175" alt="Image" src="https://github.com/user-attachments/assets/9310f95a-9467-46d7-9052-f961fe5e4c03" />
Author
Owner

@hornjbl commented on GitHub (Feb 1, 2026):

Bump

@hornjbl commented on GitHub (Feb 1, 2026): Bump
Author
Owner

@rossdargan commented on GitHub (Feb 2, 2026):

I have encounted this same bug, and it was very confusing - here is the bug report I was about to submit:

I use a http api (jhonderson/actual-http-api) to import transaction directly from by bank (they will call a webhook for me). I correctly set the import_id to the banks transaction id. This is the payload I was sending to the import endpoint:

{
  "transactions": [
    {
      "account": "bd7f8f58-d2dd-4d69-8b65-2ff33277b32e",
      "amount": -400,
      "cleared": false,
      "date": "2026-02-02",
      "imported_id": "tx_0000B2tifWA246VuYFmim2",
      "notes": "08327435/01-244",
      "payee_name": "World Animal Protection"
    }
  ]
}

I had a transaction that looks like this:
Image

The import process matched the £4 to an already cleared split. This matching just makes no sense. The transaction was cleared, and the amount was £7, with a split for £4

Looking at the API I can see this now:

		{
			"id": "a5202007-e83b-4234-adc3-23e722f4394a",
			"is_parent": true,
			"is_child": false,
			"parent_id": null,
			"account": "bd7f8f58-d2dd-4d69-8b65-2ff33277b32e",
			"category": null,
			"amount": -700,
			"payee": "629b84f0-a90d-4c5a-aa58-3bf2785d4d03",
			"notes": "#👩‍🦰 ",
			"date": "2026-01-31",
			"imported_id": "tx_0000B2qTvGUzyw4J401oOn",
			"error": null,
			"imported_payee": "Victoria Road St Bened",
			"starting_balance_flag": false,
			"transfer_id": null,
			"sort_order": 1769866653310,
			"cleared": true,
			"reconciled": false,
			"tombstone": false,
			"schedule": null,
			"raw_synced_data": null,
			"subtransactions": [
				{
					"id": "a5a4e9f8-bafc-44e8-bb6e-392a8eea819c",
					"is_parent": false,
					"is_child": true,
					"parent_id": "a5202007-e83b-4234-adc3-23e722f4394a",
					"account": "bd7f8f58-d2dd-4d69-8b65-2ff33277b32e",
					"category": "0e03b4e8-80b9-4484-8796-512a98009f17",
					"amount": -400,
					"payee": "629b84f0-a90d-4c5a-aa58-3bf2785d4d03",
					"notes": "LJ Top",
					"date": "2026-01-31",
					"imported_id": "tx_0000B2tifWA246VuYFmim2", // NOTE THIS IS HOW I SPOTTED IT
					"error": null,
					"imported_payee": "World Animal Protection",
					"starting_balance_flag": false,
					"transfer_id": null,
					"sort_order": -1,
					"cleared": true,
					"reconciled": false,
					"tombstone": false,
					"schedule": null,
					"raw_synced_data": null
				},
				{
					"id": "785ed4cb-b237-4958-81a6-b91aafd7c240",
					"is_parent": false,
					"is_child": true,
					"parent_id": "a5202007-e83b-4234-adc3-23e722f4394a",
					"account": "bd7f8f58-d2dd-4d69-8b65-2ff33277b32e",
					"category": "911eb81f-5776-4312-a710-5c9a9449f1d4",
					"amount": -300,
					"payee": "629b84f0-a90d-4c5a-aa58-3bf2785d4d03",
					"notes": "Murder Mystery",
					"date": "2026-01-31",
					"imported_id": null,
					"error": null,
					"imported_payee": null,
					"starting_balance_flag": false,
					"transfer_id": null,
					"sort_order": -2,
					"cleared": true,
					"reconciled": false,
					"tombstone": false,
					"schedule": null,
					"raw_synced_data": null
				}
			]
		},

It was really hard to track this down too, as this transaction was 2 days earlier.

I have this particular transaction setup as a scheduled transaction, but don't have it automatically adding it to my budget. Would that be a suitable workaround for now?

@rossdargan commented on GitHub (Feb 2, 2026): I have encounted this same bug, and it was very confusing - here is the bug report I was about to submit: I use a http api (jhonderson/actual-http-api) to import transaction directly from by bank (they will call a webhook for me). I correctly set the import_id to the banks transaction id. This is the payload I was sending to the import endpoint: ``` json { "transactions": [ { "account": "bd7f8f58-d2dd-4d69-8b65-2ff33277b32e", "amount": -400, "cleared": false, "date": "2026-02-02", "imported_id": "tx_0000B2tifWA246VuYFmim2", "notes": "08327435/01-244", "payee_name": "World Animal Protection" } ] } ``` I had a transaction that looks like this: <img width="1385" height="93" alt="Image" src="https://github.com/user-attachments/assets/7157b98b-3964-4503-81d5-8d451cae8bcc" /> The import process matched the £4 to an already cleared split. This matching just makes no sense. The transaction was cleared, and the amount was £7, with a split for £4 Looking at the API I can see this now: ``` json { "id": "a5202007-e83b-4234-adc3-23e722f4394a", "is_parent": true, "is_child": false, "parent_id": null, "account": "bd7f8f58-d2dd-4d69-8b65-2ff33277b32e", "category": null, "amount": -700, "payee": "629b84f0-a90d-4c5a-aa58-3bf2785d4d03", "notes": "#👩‍🦰 ", "date": "2026-01-31", "imported_id": "tx_0000B2qTvGUzyw4J401oOn", "error": null, "imported_payee": "Victoria Road St Bened", "starting_balance_flag": false, "transfer_id": null, "sort_order": 1769866653310, "cleared": true, "reconciled": false, "tombstone": false, "schedule": null, "raw_synced_data": null, "subtransactions": [ { "id": "a5a4e9f8-bafc-44e8-bb6e-392a8eea819c", "is_parent": false, "is_child": true, "parent_id": "a5202007-e83b-4234-adc3-23e722f4394a", "account": "bd7f8f58-d2dd-4d69-8b65-2ff33277b32e", "category": "0e03b4e8-80b9-4484-8796-512a98009f17", "amount": -400, "payee": "629b84f0-a90d-4c5a-aa58-3bf2785d4d03", "notes": "LJ Top", "date": "2026-01-31", "imported_id": "tx_0000B2tifWA246VuYFmim2", // NOTE THIS IS HOW I SPOTTED IT "error": null, "imported_payee": "World Animal Protection", "starting_balance_flag": false, "transfer_id": null, "sort_order": -1, "cleared": true, "reconciled": false, "tombstone": false, "schedule": null, "raw_synced_data": null }, { "id": "785ed4cb-b237-4958-81a6-b91aafd7c240", "is_parent": false, "is_child": true, "parent_id": "a5202007-e83b-4234-adc3-23e722f4394a", "account": "bd7f8f58-d2dd-4d69-8b65-2ff33277b32e", "category": "911eb81f-5776-4312-a710-5c9a9449f1d4", "amount": -300, "payee": "629b84f0-a90d-4c5a-aa58-3bf2785d4d03", "notes": "Murder Mystery", "date": "2026-01-31", "imported_id": null, "error": null, "imported_payee": null, "starting_balance_flag": false, "transfer_id": null, "sort_order": -2, "cleared": true, "reconciled": false, "tombstone": false, "schedule": null, "raw_synced_data": null } ] }, ``` It was really hard to track this down too, as this transaction was 2 days earlier. I have this particular transaction setup as a scheduled transaction, but don't have it automatically adding it to my budget. Would that be a suitable workaround for now?
Author
Owner

@matt-fidd commented on GitHub (Feb 5, 2026):

I feel like I've seen this before. We should probably prevent splits from matching to transactions, as the whole point is that they should be a part of a larger transaction that would match.

@matt-fidd commented on GitHub (Feb 5, 2026): I feel like I've seen this before. We should probably prevent splits from matching to transactions, as the whole point is that they should be a part of a larger transaction that would match.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#2847