{"record":{"id":"744a5510f4693b11","repo":"actualbudget/actual","slug":"results-reason","errorCode":null,"errorMessage":"results.reason","messagePattern":"results\\.reason","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/banksync/useBuiltInBankSyncProviders.ts","lineNumber":501,"sourceCode":"    }\n  }, [\n    dispatch,\n    isEnableBankingSetupComplete,\n    onEnableBankingInit,\n    t,\n    upgradingAccountId,\n  ]);\n\n  const onConnectPluggyAi = useCallback(async () => {\n    if (!pluggyAiStatus.configured) {\n      onPluggyAiInit();\n      return;\n    }\n\n    try {\n      const results = await send('pluggyai-accounts');\n      if (results.error_code) {\n        throw new Error(results.reason);\n      }\n      if ('error' in results) {\n        throw new Error(results.error);\n      }\n\n      const externalAccounts = (results.accounts as PluggyAiAccount[]).map(\n        oldAccount => ({\n          account_id: oldAccount.id,\n          name: `${oldAccount.name.trim()} - ${\n            oldAccount.type === 'BANK' ? oldAccount.taxNumber : oldAccount.owner\n          }`,\n          institution: oldAccount.name,\n          orgDomain: null,\n          orgId: oldAccount.id,\n          balance:\n            oldAccount.type === 'BANK'\n              ? oldAccount.bankData.automaticallyInvestedBalance +\n                oldAccount.bankData.closingBalance","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/banksync/useBuiltInBankSyncProviders.ts#L483-L519","documentation":"When fetching Pluggy.ai accounts, an error_code in the 'pluggyai-accounts' response is thrown with results.reason as the message. Note this branch does not fall back to the code itself, so an empty reason yields an empty error message.","triggerScenarios":"The 'pluggyai-accounts' IPC returns { error_code: <non-null> } — e.g. invalid Pluggy.ai client id/secret, expired Pluggy auth, or the server failing to reach the Pluggy.ai API.","commonSituations":"Mis-typed pluggyai_clientId or pluggyai_clientSecret stored in secrets; per-budget-file vs global secret scope mismatch; Pluggy.ai API outage.","solutions":["Check results.reason (and server logs) for the Pluggy.ai failure cause","Re-enter Pluggy.ai credentials via the provider settings so secret-set stores valid values","Confirm the secret scope matches pluggyAiStatus.source (global vs per-budget-file)","Verify network access from the sync server to api.pluggy.ai"],"exampleFix":"// before\nif (results.error_code) {\n  throw new Error(results.reason);\n}\n// after\nif (results.error_code) {\n  throw new Error(results.reason || results.error_code);\n}","handlingStrategy":"try-catch","validationCode":"const res = await send('pluggyai-accounts');\nif (res.error_code) {\n  throw new Error(res.reason || res.error_code);\n}","typeGuard":"const isPluggyError = (r: object): r is { error_code?: string; reason?: string; error?: string } =>\n  'error_code' in r || 'error' in r;","tryCatchPattern":"try {\n  await loadPluggyAiAccounts();\n} catch (e) {\n  notify(`Pluggy.ai failed: ${e instanceof Error ? e.message : String(e)}`);\n}","preventionTips":["Validate Pluggy.ai clientId/secret before saving them as secrets","Ensure the secret scope (global vs per-budget-file) matches the provider source","Check Pluggy.ai status/uptime before debugging app-side"],"tags":["banksync","pluggyai","api-error","credentials"],"backgroundTag":"bank-sync-provider-error","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}