actualbudget/actual · error · BankSyncError
TIMED_OUT
TIMED_OUT
Error message
TIMED_OUT
What it means
downloadSimpleFinTransactions wraps its HTTP post in a try/catch with a 60s timeout for single-account syncs and 300s for batch syncs (sync.ts:211-217). Any failure of that request — including the configured timeout firing — is logged and rethrown as BankSyncError('TIMED_OUT', 'TIMED_OUT'). It indicates the SimpleFin server did not respond in time, not necessarily that the bank itself failed.
Source
Thrown at packages/loot-core/src/server/accounts/sync.ts:216
logger.log('Pulling transactions from SimpleFin');
let res;
try {
res = await post(
getServer().SIMPLEFIN_SERVER + '/transactions',
{
accountId: acctId,
startDate: since,
},
{
'X-ACTUAL-TOKEN': userToken,
},
// 5 minute timeout for batch sync, one minute for individual accounts
Array.isArray(acctId) ? 300000 : 60000,
);
} catch (error) {
logger.error('Suspected timeout during bank sync:', error);
throw BankSyncError('TIMED_OUT', 'TIMED_OUT');
}
if (Object.keys(res).length === 0) {
throw BankSyncError('NO_DATA', 'NO_DATA');
}
if (res.error_code) {
throw BankSyncError(res.error_type, res.error_code);
}
let retVal = {};
if (batchSync) {
const batchErrors = res.errors;
for (const accountId of Object.keys(res)) {
if (accountId === 'errors') continue;
const data = res[accountId];
const error = batchErrors?.[accountId]?.[0];
View on GitHub (pinned to d4334cb6e6)
Solutions
- Retry the sync — timeouts are often transient; consider syncing accounts in smaller batches to stay under the 300s batch limit.
- Check connectivity from the sync server to the SimpleFin server URL (getServer().SIMPLEFIN_SERVER).
- Reduce the number of accounts in a batch sync so the request completes within the timeout.
- Verify the SimpleFin access URL/claims token is current; stale setup URLs cause slow failed lookups.
Defensive patterns
Strategy: retry
Validate before calling
// Keep batches small enough to finish within the 300s batch timeout:
if (Array.isArray(acctIds) && acctIds.length > 25) {
throw new Error('Batch too large — split into smaller groups to avoid SimpleFin timeouts');
} Type guard
function isTimedOutError(e: unknown): boolean {
return typeof e === 'object' && e !== null &&
(e as { errorType?: string }).errorType === 'TIMED_OUT' &&
(e as { errorCode?: string }).errorCode === 'TIMED_OUT';
} Try / catch
try {
await syncAccount(accountId);
} catch (e) {
if (isTimedOutError(e)) {
await delay(5000);
await syncAccount(accountId); // retry with backoff, smaller batch
} else throw e;
} Prevention
- Retry with exponential backoff — SimpleFin aggregation can be transiently slow.
- Split large batch syncs into per-account or small-group syncs.
- Verify network/DNS from the sync server to SIMPLEFIN_SERVER.
- Avoid overlapping scheduled syncs that contend for the same slow provider.
When it happens
Trigger: SimpleFin /transactions call exceeding the 60000ms (single account) or 300000ms (batch array) timeout, or the post throwing a network error; occurs inside syncAccount via downloadSimpleFinTransactions.
Common situations: Slow bank aggregation on SimpleFin's side; very large batch syncs of many accounts; network issues between sync server and SimpleFin; self-hosted setups with slow DNS/proxy.
Related errors
- results.reason || results.error_code
- results.reason || results.error
- TIMED_OUT
- SimpleFIN claim failed with HTTP ${response.status}
- Too many redirects
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/b788ceeca520f934.
Report an issue: GitHub.