{"record":{"id":"9a5d3f941e124559","repo":"actualbudget/actual","slug":"sync-error","errorCode":"SYNC_ERROR","errorMessage":"SYNC_ERROR","messagePattern":"SYNC_ERROR","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/accounts/syncStatus.ts","lineNumber":36,"sourceCode":"  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":18,"sourceCodeEnd":39,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/accounts/syncStatus.ts#L18-L39","documentation":"The default branch of getFailedSyncError: any bank_sync_status value not explicitly handled resolves to SYNC_ERROR. It is a generic catch-all meaning the last bank sync failed for an unclassified reason and the specific provider error should be inspected in logs.","triggerScenarios":"Calling getFailedSyncError with bank_sync_status undefined or set to any unrecognized string (anything other than reauth-required, attention-required, rate-limit-exceeded, timed-out, account-missing), typically an unknown/failed status stored after a sync failure.","commonSituations":"Schema or version drift between server-side status values and this client switch; corrupted or legacy account rows; miscellaneous sync failures (provider 500s, parsing errors).","solutions":["Check server/bank-sync logs for the underlying provider error","Verify the server's bank_sync_status values match the cases handled in syncStatus.ts (version drift)","Run a fresh manual sync and re-read the resulting status","If a new status value exists upstream, add an explicit case to getFailedSyncError instead of relying on the default"],"exampleFix":"// before\n// server writes 'provider-outage', client switch has no case -> SYNC_ERROR\n// after\nif (getFailedSyncError(account).code === 'SYNC_ERROR') {\n  inspectServerLogs(account.id); // find the real provider error\n}","handlingStrategy":"type-guard","validationCode":"const KNOWN_STATUSES = ['reauth-required','attention-required','rate-limit-exceeded','timed-out','account-missing'];\nfunction hasKnownStatus(account) {\n  return KNOWN_STATUSES.includes(account.bank_sync_status);\n}","typeGuard":"function isKnownSyncStatus(v) {\n  return ['reauth-required','attention-required','rate-limit-exceeded','timed-out','account-missing'].includes(v);\n}","tryCatchPattern":null,"preventionTips":["Keep server-side status enum and the client switch in sync (shared type)","Log the unexpected bank_sync_status value when hitting the default branch","Treat SYNC_ERROR as a signal to inspect provider logs, not to retry blindly"],"tags":["bank-sync","fallback","unclassified"],"backgroundTag":"unclassified-sync-error","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}