{"record":{"id":"8d41d1750ca777ae","repo":"actualbudget/actual","slug":"results-reason-results-error-code","errorCode":null,"errorMessage":"results.reason || results.error_code","messagePattern":"results\\.reason \\|\\| results\\.error_code","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/banksync/useBuiltInBankSyncProviders.ts","lineNumber":411,"sourceCode":"    if (!isSimpleFinSetupComplete) {\n      onSimpleFinInit();\n      return;\n    }\n\n    if (loadingSimpleFinAccounts) {\n      return;\n    }\n\n    setLoadingSimpleFinAccounts(true);\n\n    try {\n      const results = await send('simplefin-accounts');\n      if (results.error_code === 'INVALID_ACCESS_TOKEN') {\n        onSimpleFinInit();\n        return;\n      }\n      if (results.error_code) {\n        throw new Error(results.reason || results.error_code);\n      }\n      if ('error' in results && results.error) {\n        throw new Error(results.reason || results.error);\n      }\n\n      const externalAccounts: SyncServerSimpleFinAccount[] = (\n        (results.accounts ?? []) as SimpleFinAccount[]\n      ).map(oldAccount => ({\n        account_id: oldAccount.id,\n        name: oldAccount.name,\n        institution: oldAccount.org.name,\n        orgDomain: oldAccount.org.domain,\n        orgId: oldAccount.org.id,\n        balance: oldAccount.balance,\n      }));\n\n      dispatch(\n        pushModal({","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/banksync/useBuiltInBankSyncProviders.ts#L393-L429","documentation":"When fetching SimpleFin accounts, any server response carrying an error_code (other than the specially handled INVALID_ACCESS_TOKEN) is converted to a thrown Error whose message is the human-readable reason or the raw error code. This surfaces server-side SimpleFin failures to the bank-sync UI.","triggerScenarios":"The 'simplefin-accounts' IPC returns { error_code: <something not INVALID_ACCESS_TOKEN> } — e.g. the SimpleFin bridge URL is invalid, the server cannot reach SimpleFin, or the access-nature token is rejected in a non-token-expiry way.","commonSituations":"Expired or revoked SimpleFin access token pasted into settings; wrong SimpleFin bridge URL; SimpleFin API outage or network failure from the sync server.","solutions":["Read results.reason in the thrown message to identify the SimpleFin failure; fix the underlying cause","Re-authenticate SimpleFin: get a fresh access token from your SimpleFin bridge and update settings","If INVALID_ACCESS_TOKEN, use the handled re-init flow (onSimpleFinInit) to re-enter credentials","Check sync-server logs and network connectivity to the SimpleFin bridge"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const res = await send('simplefin-accounts');\nif (res.error_code === 'INVALID_ACCESS_TOKEN') { reinitSimpleFin(); }\nelse if (res.error_code || ('error' in res && res.error)) {\n  throw new Error(res.reason || res.error_code || res.error);\n}","typeGuard":"const isSimpleFinError = (r: object): r is { error_code?: string; reason?: string; error?: string } =>\n  'error_code' in r || 'error' in r;","tryCatchPattern":"try {\n  await loadSimpleFinAccounts();\n} catch (e) {\n  notify(`SimpleFin failed: ${e instanceof Error ? e.message : String(e)}`);\n}","preventionTips":["Refresh the SimpleFin access token before it expires","Verify the SimpleFin bridge URL is reachable from the sync server","Handle INVALID_ACCESS_TOKEN by re-running the init flow instead of surfacing an error"],"tags":["banksync","simplefin","network","api-error"],"backgroundTag":"bank-sync-provider-error","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}