{"record":{"id":"766dd84a23da6a37","repo":"actualbudget/actual","slug":"transaction-transactionid-not-found","errorCode":null,"errorMessage":"Transaction ${transactionId} not found","messagePattern":"Transaction (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/mobile/transactions/TransactionEdit.tsx","lineNumber":947,"sourceCode":"      },\n      [onUpdateInner, transaction],\n    );\n\n    const onEditFieldInner = useCallback(\n      (\n        transactionId: TransactionEntity['id'],\n        name: 'category' | 'payee' | 'account' | 'date' | 'amount' | 'notes',\n      ) => {\n        onRequestActiveEdit?.(getFieldName(transaction.id, name), () => {\n          const transactionToEdit = transactions.find(\n            t => t.id === transactionId,\n          );\n          const unserializedTransaction = unserializedTransactions.find(\n            t => t.id === transactionId,\n          );\n\n          if (!unserializedTransaction || !transactionToEdit) {\n            throw new Error(`Transaction ${transactionId} not found`);\n          }\n\n          switch (name) {\n            case 'category':\n              dispatch(\n                pushModal({\n                  modal: {\n                    name: 'category-autocomplete',\n                    options: {\n                      categoryGroups,\n                      showHiddenCategories,\n                      showNoneOption: true,\n                      month: monthUtils.monthFromDate(\n                        unserializedTransaction.date,\n                      ),\n                      onSelect: categoryId => {\n                        void onUpdateInner(\n                          transactionToEdit,","sourceCodeStart":929,"sourceCodeEnd":965,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.tsx#L929-L965","documentation":"TransactionEdit throws when handling an edit-field action (e.g. category change) but neither the transaction with `transactionId` nor the expected `transactionToEdit` can be found in `unserializedTransactions`. It indicates the modal's action referenced a transaction that is no longer loaded in the component's state. Thrown as an invariant to prevent editing a nonexistent transaction.","triggerScenarios":"A modal callback fires with a `transactionId` whose transaction is absent from the local `unserializedTransactions` array, or `transactionToEdit` is null — e.g. the transaction was deleted/split elsewhere, or the id lookup happens before transactions finish loading.","commonSituations":"Editing a transaction from a stale list after it was deleted on another device; opening TransactionEdit via deep link with an id that isn't in the current query results; race where a modal action fires during a state refresh.","solutions":["Reload the transactions list / refetch the transaction and retry the edit.","Confirm the transaction still exists (it may have been deleted or the id changed after a split).","Guard the switch: if the transaction is missing, close the modal and show a 'transaction no longer exists' message instead of throwing.","Check that the id passed into TransactionEdit matches the id in the transactions store (no id transformation)."],"exampleFix":"// before\nif (!unserializedTransaction || !transactionToEdit) {\n  throw new Error(`Transaction ${transactionId} not found`);\n}\n// after\nif (!unserializedTransaction || !transactionToEdit) {\n  dispatch(closeModal());\n  dispatch(addNotification({ message: t('Transaction no longer exists') }));\n  return;\n}","handlingStrategy":"validation","validationCode":"const unserializedTransaction = unserializedTransactions.find(t => t.id === transactionId);\nif (!unserializedTransaction) {\n  dispatch(closeModal());\n  dispatch(addNotification({ message: t('Transaction no longer exists') }));\n  return;\n}","typeGuard":"function transactionExists(id: string, txs: { id: string }[]): boolean {\n  return txs.some(t => t.id === id);\n}","tryCatchPattern":"try {\n  onEditField(name, value);\n} catch (err) {\n  if (String(err).startsWith('Transaction')) {\n    dispatch(closeModal());\n    void reloadTransactions();\n  } else {\n    throw err;\n  }\n}","preventionTips":["Refetch/reload transactions when the edit modal is about to act on a stale id.","Close dependent modals whenever the underlying transaction list changes.","Never pass ids from long-lived caches; read them from current query results."],"tags":["react","transactions","state-desync","mobile"],"backgroundTag":"entity-not-found-in-collection","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}