actualbudget/actual · error · BankSyncError
Connection
Connection
Error message
Connection
What it means
downloadPluggyAiTransactions throws BankSyncError('Connection', res.error) when the Pluggy.ai response has a generic 'error' field but no structured error_code. This indicates a connection-level or non-standard failure communicated by the sync server/proxy rather than a categorized provider error code.
Source
Thrown at packages/loot-core/src/server/accounts/sync.ts:304
logger.log('Pulling transactions from Pluggy.ai');
const res = await post(
getServer().PLUGGYAI_SERVER + '/transactions',
{
accountId: acctId,
startDate: since,
},
{
'X-ACTUAL-TOKEN': userToken,
...(fileId ? { 'X-Actual-File-Id': fileId } : {}),
},
60000,
);
if (res.error_code) {
throw BankSyncError(res.error_type, res.error_code);
} else if ('error' in res) {
throw BankSyncError('Connection', res.error);
}
let retVal = {};
const singleRes = res as BankSyncResponse;
retVal = {
transactions: singleRes.transactions.all,
accountBalance: singleRes.balances,
startingBalance: singleRes.startingBalance,
};
logger.log('Response:', retVal);
return retVal;
}
async function downloadAkahuTransactions(
acctId: AccountEntity['id'],
since: string,
) {View on GitHub (pinned to d4334cb6e6)
Solutions
- Read res.error from the thrown BankSyncError to see the underlying message
- Verify the sync server has Pluggy credentials configured (PLUGGY_CLIENT_ID, PLUGGY_CLIENT_SECRET env vars)
- Check sync-server logs for the failing upstream request and confirm the server can reach api.pluggy.ai
- Retry the sync after confirming server connectivity
Example fix
// before: sync server missing Pluggy env vars # .env # (PLUGGY_CLIENT_ID and PLUGGY_CLIENT_SECRET absent) // after # .env PLUGGY_CLIENT_ID=your-client-id PLUGGY_CLIENT_SECRET=your-client-secret # then restart the sync server and retry sync
Defensive patterns
Strategy: retry
Validate before calling
if (!syncServerUrl.startsWith('https://')) {
throw new Error('Sync server URL must be reachable over HTTPS');
} Try / catch
async function syncWithRetry(accountId, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await runQuery(syncAccount(accountId));
} catch (e) {
if (e.type === 'BankSyncError' && e.code === 'Connection' && i < attempts - 1) {
await new Promise(r => setTimeout(r, 2000 * (i + 1)));
continue;
}
throw e;
}
}
} Prevention
- Ensure the sync server has outbound access to api.pluggy.ai
- Set Pluggy env vars on self-hosted sync servers before enabling the bank
- Monitor sync-server logs for upstream proxy errors
- Use HTTPS endpoints without intermediate error pages that break JSON parsing
When it happens
Trigger: syncAccount on a Pluggy.ai account where the fetch to /pluggy/... returns JSON containing an 'error' key (e.g. sync-server proxy error, missing Pluggy credentials configured on the server, malformed upstream response).
Common situations: Self-hosted sync server without PLUGGY_CLIENT_ID/PLUGGY_CLIENT_SECRET set; network/proxy failure between the sync server and Pluggy; server returns an HTML/JSON error page parsed into res.error.
Related errors
- Unrecognized bank-sync provider: ${acctRow.account_sync_sour
- Provided account id is not linked to given requisition
- response.reason || response.error_code
- response.reason || response.error || fallbackMessage
- Error loading data into the spreadsheet.
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/373b690a73dc7cfc.
Report an issue: GitHub.