actualbudget / actualbudget/actual
ING Direct (ING_INGBITMM) fails to link: a pre-created end-user agreement leaves the requisition stuck in UA
- Lenguaje dominante
- TypeScript
- Estrellas
- 28.7k
- Forks
- 3k
- Merge medio
- 2 d 11 h
- PR fusionados (30 d)
- 65
Descripción
## What happens
Linking an ING Direct (Italy, `ING_INGBITMM`) account through GoCardless never completes. After authenticating at ING, the GoCardless hosted page returns:
```
400
Session expired
Session interrupted or has been already authorized
```
The requisition stays in `UA` (undergoing authentication) and never reaches `LN`, so no accounts are imported. It reproduces on every attempt.
## Environment
- actual-server 26.9.0, self-hosted (Docker)
- Institution `ING_INGBITMM`, GoCardless (Bank Account Data) API
- Reproduced both from the normal browser link flow and against the GoCardless API directly
## Cause
`initSession` always creates an explicit end-user agreement and binds the requisition to it:
```js
async initSession({ ... }) {
const agreement = await this.createAgreement({ institutionId, maxHistoricalDays, accessValidForDays });
return this.createRequisition({ ..., agreement: agreement.id });
}
```
`ING_INGBITMM` cannot finalize a requisition that is bound to a pre-created agreement object. The consent is accepted on ING's side (the agreement flips to `accepted: true`), but GoCardless never advances the requisition past `UA`.
## Isolation
Same institution, same bank account, requisitions created minutes apart in the same window:
- WITHOUT an `agreement` field (GoCardless auto-creates its default): reaches `LN` with both accounts on the first try.
- WITH a pre-created agreement at `access_valid_for_days: 180`, `max_historical_days: 730` (the values Actual sends for ING): stuck in `UA`.
- WITH a pre-created agreement at `90 / 90`: also stuck in `UA`.
The auto-created default agreement is itself `90 / 90`, so the scope is not the trigger. What decides success is whether the agreement is a separate pre-created object referenced by id, or created inline by GoCardless during requisition creation.
Other institutions (e.g. BBVA) link fine either way, so this is specific to ING's connector honouring `supported_features` it can't actually deliver through an explicit agreement.
## Workaround
Patching the bundled server to drop the agreement id (`agreement: agreement.id` → `agreement: void 0`) makes ING link on the first try; GoCardless then auto-creates the default agreement inline.
Guía de contribución
Evaluación
Este issue todavía no se ha evaluado.