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

  1. Read res.error from the thrown BankSyncError to see the underlying message
  2. Verify the sync server has Pluggy credentials configured (PLUGGY_CLIENT_ID, PLUGGY_CLIENT_SECRET env vars)
  3. Check sync-server logs for the failing upstream request and confirm the server can reach api.pluggy.ai
  4. 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

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


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/373b690a73dc7cfc. Report an issue: GitHub.