actualbudget/actual · error · AccountNotLinkedToRequisition

Provided account id is not linked to given requisition

Error message

Provided account id is not linked to given requisition

What it means

In getTransactionsWithBalance, the sync-server first loads the GoCardless requisition (a bank link/session) via getLinkedRequisition and reads the list of account ids it contains. If the accountId requested for transactions+balance is not one of the accounts in that requisition, it throws AccountNotLinkedToRequisition. This guard prevents querying GoCardless for an account that was never part of the bank connection, which would fail at the API anyway.

Source

Thrown at packages/sync-server/src/app-gocardless/services/gocardless-service.ts:216

    requisitionId: GoCardlessRequisitionId,
    accountId: GoCardlessAccountId,
    startDate: string | undefined,
    endDate: string | undefined,
  ): Promise<{
    balances: Balance[];
    institutionId: GoCardlessInstitutionId;
    startingBalance: number;
    transactions: {
      booked: Transaction[];
      pending: Transaction[];
      all: TransactionWithBookedStatus[];
    };
  }> => {
    const { institution_id, accounts: accountIds } =
      await goCardlessService.getLinkedRequisition(requisitionId);

    if (!accountIds.includes(accountId)) {
      throw new AccountNotLinkedToRequisition(accountId, requisitionId);
    }

    const [normalizedTransactions, accountBalance] = await Promise.all([
      goCardlessService.getNormalizedTransactions(
        requisitionId,
        accountId,
        startDate,
        endDate,
      ),
      goCardlessService.getBalances(accountId),
    ]);

    const transactions = normalizedTransactions.transactions;

    const bank: IBank = BankFactory(institution_id);

    const startingBalance = bank.calculateStartingBalance(
      transactions.booked,

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Verify the accountId belongs to the requisition: GET the requisition's linked accounts and use one of those ids.
  2. Re-run the bank link flow (accounts list step) so the budget's account mappings match the current requisition's accounts.
  3. If the bank added/replaced accounts after linking, delete and re-create the GoCardless link in Actual so account ids are refreshed.
  4. Check for a typo or mixed-up requisitionId/accountId pair when calling the API directly.

Example fix

// before
await goCardlessService.getTransactionsWithBalance('req-ABC', 'acct-XYZ', start, end);

// after
const { accounts } = await goCardlessService.getLinkedRequisition('req-ABC');
if (!accounts.includes('acct-XYZ')) {
  throw new Error(`acct-XYZ not in req-ABC; available: ${accounts.join(',')}`);
}
await goCardlessService.getTransactionsWithBalance('req-ABC', 'acct-XYZ', start, end);
Defensive patterns

Strategy: validation

Validate before calling

const { accounts } = await goCardlessService.getLinkedRequisition(requisitionId);
if (!accounts.includes(accountId)) {
  throw new Error(`account ${accountId} not linked to requisition ${requisitionId}`);
}

Prevention

When it happens

Trigger: Calling goCardlessService.getTransactionsWithBalance(requisitionId, accountId, ...) where accountId is not present in the `accounts` array returned by getLinkedRequisition(requisitionId) — e.g. pairing an account id from a different bank link, or a stale/renumbered account id after a re-link.

Common situations: Bank connections were re-established and the old requisition now links a new set of account ids while the budget still references the old account; a copy/paste mistake mixing ids across two GoCardless bank connections; a deleted or revoked requisition replaced by a new one with different account ids.

Related errors


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