actualbudget/actual · error · RequisitionNotLinked
Requisition not linked yet
Error message
Requisition not linked yet
What it means
gocardless-service fetches a requisition and only continues when its status is 'LN' (linked), meaning the end user finished the bank authorization. Any other status throws RequisitionNotLinked carrying the actual requisitionStatus.
Solutions
- Have the user re-run the link flow (create a new requisition and complete bank authorization) to reach status LN
- Inspect the returned requisitionStatus to decide the message shown to the user (expired vs rejected vs pending)
- If status is CR, send the user to the requisition link URL to finish authorization
- Delete the stale requisition/account in the UI and re-add the bank connection
Example fix
// before
const accounts = await gocardlessService.getRequisitionWithAccounts(reqId); // throws if not LN
// after
const req = await gocardlessService.getRequisition(reqId);
if (req.status !== 'LN') {
// prompt user to re-authenticate / re-create the link
await restartLinkFlow(institutionId);
return;
}
const accounts = await gocardlessService.getRequisitionWithAccounts(reqId); Defensive patterns
Strategy: try-catch
Try / catch
try {
const requisition = await getRequisition(reqId);
} catch (e) {
if (e instanceof RequisitionNotLinked) {
switch (e.details?.requisitionStatus) {
case 'CR': promptUserToFinishBankAuth(e.details.link); break;
case 'EX': case 'RJ': case 'GC':
default: await recreateRequisition(institutionId); // re-link flow
}
} else throw e;
} Prevention
- Only query accounts after the user completes the bank authorization redirect
- Check requisition status before polling and surface pending states in the UI
- Expect 90-day consent expiry and plan periodic re-linking
- Persist the requisition link URL so users can resume an interrupted authorization
When it happens
Trigger: Polling/reading accounts for a requisition whose status is e.g. 'RJ' (rejected/suspended), 'EX' (expired), 'CR' (created but not yet continued), or 'GC' (cancelled) — i.e. the user never completed (or failed) the bank consent flow.
Common situations: User closed the bank auth window without approving; bank rejected the PSU or the consent expired; server tried to sync a bank connection before the user finished linking; requisition link expired after 90 days per GoCardless.
Related errors
- Account with ID not found.
- ITEM_LOGIN_REQUIRED
- Provided account id is not linked to given requisition
- res.error_code
- ACCOUNT_MISSING
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/0b5b7b8962335405.
Report an issue: GitHub.
Appendix: source
Thrown at packages/sync-server/src/app-gocardless/services/gocardless-service.ts:144
}
};
if (isExpiredJwtToken(getGocardlessClient().token)) {
await client.generateToken().catch(handleGoCardlessError);
}
},
getLinkedRequisition: async (
requisitionId: GoCardlessRequisitionId,
): Promise<Requisition> => {
const requisition = await goCardlessService.getRequisition(requisitionId);
const { status } = requisition;
// Continue only if status of requisition is "LN" which
// means the account has been successfully linked to the requisition
if (status !== 'LN') {
throw new RequisitionNotLinked({ requisitionStatus: status });
}
return requisition;
},
getRequisitionWithAccounts: async (
requisitionId: GoCardlessRequisitionId,
): Promise<{
requisition: Requisition;
accounts: NormalizedAccountDetails[];
}> => {
const requisition =
await goCardlessService.getLinkedRequisition(requisitionId);
console.log('GoCardless requisition linked:', {
institutionId: requisition.institution_id,
requisitionId,
agreementId: requisition.agreement,View on GitHub (pinned to d4334cb6e6)