{"record":{"id":"ad98ea4de773152e","repo":"actualbudget/actual","slug":"item-login-required","errorCode":"ITEM_LOGIN_REQUIRED","errorMessage":"ITEM_ERROR","messagePattern":"ITEM_ERROR","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/accounts/syncStatus.ts","lineNumber":23,"sourceCode":") {\n  const status = account.bank_sync_status;\n  return (\n    status != null &&\n    status !== 'ok' &&\n    status !== 'pending' &&\n    status !== 'sync-requested'\n  );\n}\n\nexport function getFailedSyncError(\n  account: Pick<AccountEntity, 'bank_sync_status' | 'account_sync_source'>,\n): { type: string; code: string } {\n  switch (account.bank_sync_status) {\n    case 'reauth-required':\n      if (account.account_sync_source === 'simpleFin') {\n        return { type: 'INVALID_ACCESS_TOKEN', code: 'INVALID_ACCESS_TOKEN' };\n      }\n      return { type: 'ITEM_ERROR', code: 'ITEM_LOGIN_REQUIRED' };\n    case 'attention-required':\n      return {\n        type: 'ACCOUNT_NEEDS_ATTENTION',\n        code: 'ACCOUNT_NEEDS_ATTENTION',\n      };\n    case 'rate-limit-exceeded':\n      return { type: 'RATE_LIMIT_EXCEEDED', code: 'RATE_LIMIT_EXCEEDED' };\n    case 'timed-out':\n      return { type: 'TIMED_OUT', code: 'TIMED_OUT' };\n    case 'account-missing':\n      return { type: 'ACCOUNT_MISSING', code: 'ACCOUNT_MISSING' };\n    default:\n      return { type: 'SYNC_ERROR', code: 'SYNC_ERROR' };\n  }\n}\n","sourceCodeStart":5,"sourceCodeEnd":39,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/accounts/syncStatus.ts#L5-L39","documentation":"Returned by getFailedSyncError for accounts whose bank_sync_status is 'reauth-required' with a non-simpleFin source (e.g. goCardless). It mirrors the Plaid-style ITEM_ERROR / ITEM_LOGIN_REQUIRED contract: the bank item's login credentials or consent have lapsed and the user must log in again through the provider's link flow.","triggerScenarios":"Calling getFailedSyncError on an account with bank_sync_status === 'reauth-required' and account_sync_source other than 'simpleFin'.","commonSituations":"Bank password changed; user changed online banking credentials; bank requires periodic re-consent (PSD2/SCA with GoCardless); provider marks the item invalid.","solutions":["Trigger the Re-link flow for the account and re-authenticate with the bank","Check the provider requisition status and recreate it if expired","After successful re-link, sync the account to clear 'reauth-required'","Set a reminder to re-auth before consent expiry if the bank enforces SCA cycles"],"exampleFix":"// before\nconst err = getFailedSyncError(account); // ITEM_LOGIN_REQUIRED\n// after\nawait openBankLinkFlow(account.id); // user re-enters bank credentials","handlingStrategy":"validation","validationCode":"function needsBankRelink(account) {\n  return account.bank_sync_status === 'reauth-required' &&\n    account.account_sync_source !== 'simpleFin';\n}","typeGuard":"function isSyncErrorDescriptor(v) {\n  return !!v && typeof v === 'object' && typeof v.type === 'string' && typeof v.code === 'string';\n}","tryCatchPattern":null,"preventionTips":["Check provider item status before each scheduled sync","Track bank consent/SCA expiry dates and warn users in advance","Surface a persistent re-link prompt whenever status is 'reauth-required'"],"tags":["bank-sync","gocardless","reauth"],"backgroundTag":"bank-item-login-required","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}