{"record":{"id":"0b5b7b8962335405","repo":"actualbudget/actual","slug":"requisition-not-linked-yet","errorCode":null,"errorMessage":"Requisition not linked yet","messagePattern":"Requisition not linked yet","errorType":"exception","errorClass":"RequisitionNotLinked","httpStatus":null,"severity":"error","filePath":"packages/sync-server/src/app-gocardless/services/gocardless-service.ts","lineNumber":144,"sourceCode":"      }\n    };\n\n    if (isExpiredJwtToken(getGocardlessClient().token)) {\n      await client.generateToken().catch(handleGoCardlessError);\n    }\n  },\n\n  getLinkedRequisition: async (\n    requisitionId: GoCardlessRequisitionId,\n  ): Promise<Requisition> => {\n    const requisition = await goCardlessService.getRequisition(requisitionId);\n\n    const { status } = requisition;\n\n    // Continue only if status of requisition is \"LN\" which\n    // means the account has been successfully linked to the requisition\n    if (status !== 'LN') {\n      throw new RequisitionNotLinked({ requisitionStatus: status });\n    }\n\n    return requisition;\n  },\n\n  getRequisitionWithAccounts: async (\n    requisitionId: GoCardlessRequisitionId,\n  ): Promise<{\n    requisition: Requisition;\n    accounts: NormalizedAccountDetails[];\n  }> => {\n    const requisition =\n      await goCardlessService.getLinkedRequisition(requisitionId);\n\n    console.log('GoCardless requisition linked:', {\n      institutionId: requisition.institution_id,\n      requisitionId,\n      agreementId: requisition.agreement,","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/sync-server/src/app-gocardless/services/gocardless-service.ts#L126-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst accounts = await gocardlessService.getRequisitionWithAccounts(reqId); // throws if not LN\n// after\nconst req = await gocardlessService.getRequisition(reqId);\nif (req.status !== 'LN') {\n  // prompt user to re-authenticate / re-create the link\n  await restartLinkFlow(institutionId);\n  return;\n}\nconst accounts = await gocardlessService.getRequisitionWithAccounts(reqId);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const requisition = await getRequisition(reqId);\n} catch (e) {\n  if (e instanceof RequisitionNotLinked) {\n    switch (e.details?.requisitionStatus) {\n      case 'CR': promptUserToFinishBankAuth(e.details.link); break;\n      case 'EX': case 'RJ': case 'GC':\n      default: await recreateRequisition(institutionId); // re-link flow\n    }\n  } else throw e;\n}","preventionTips":["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"],"tags":["gocardless","bank-sync","authorization","requisition"],"backgroundTag":"requisition-not-linked","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}