Enable Banking Error Handling#
Overview#
Error handling in the Enable Banking integration spans two layers: the provider client (Provider::EnableBanking) which maps raw HTTP responses to typed exceptions, and the importer (EnableBankingItem::Importer) which translates those exceptions into user-facing messages and decides whether to abort, retry, or partially continue a sync.
Error Types and HTTP Mapping#
All API calls pass through handle_response, which maps HTTP status codes to EnableBankingError instances with a typed error_type symbol:
| HTTP code | error_type | Meaning |
|---|---|---|
| 400 | :bad_request | Malformed request (e.g. bad ASPSP name, Trade Republic PDNG rejection) |
| 401 | :unauthorized | Invalid credentials or expired JWT |
| 403 | :access_forbidden | App permissions not configured |
| 404 | :not_found | Session or account not found |
| 408 | :timeout | Enable Banking API timeout |
| 422 | :validation_error | Includes full response data; used for WRONG_TRANSACTIONS_PERIOD auto-retry and mid-pagination truncation |
| 429 | :rate_limited | Rate limit exceeded |
Network-level failures (SocketError, Net::OpenTimeout, Net::ReadTimeout) are caught at the call site and re-raised as EnableBankingError(:request_failed) .
The EnableBankingError class carries error_type, response_data, and two helpers:
wrong_transactions_period?— true whenerror_type == :validation_errorandresponse_data[:error] == "WRONG_TRANSACTIONS_PERIOD"corrected_date_from— extracts the ASPSP-suggested corrected start date fromresponse_data[:detail][:date_from]
Invalid Date Range Auto-Retry (WRONG_TRANSACTIONS_PERIOD)#
get_account_transactions automatically retries once when an ASPSP rejects the requested date range:
- The API responds with HTTP 422 and
error: "WRONG_TRANSACTIONS_PERIOD", along with adetail.date_fromspecifying the earliest date the ASPSP will accept. wrong_transactions_period?returns true andcorrected_date_fromextracts the replacement date.- The method recurses with
date_from: corrected_date_fromandretried_date_from: trueto prevent further retries . - If the corrected date equals the original, or no corrected date is present, the error propagates normally.
This retry happens inside Provider::EnableBanking, so callers (fetch_paginated_transactions) see a clean result without needing to know the retry occurred. Crucially, WRONG_TRANSACTIONS_PERIOD is not swallowed by the mid-pagination truncation logic — if it fires mid-pagination the importer propagates it rather than silently dropping remaining pages .
Provider-Specific Error Code Mapping to User-Facing Messages#
handle_sync_error in the importer classifies any exception into one of four user-facing strings (all defined in en.yml):
| Condition | i18n key | Displayed message |
|---|---|---|
| Session-level 401 or 404 | errors.session_invalid | "Session expired. Please reconnect your bank." |
Network error or :request_failed/:timeout | errors.network_unreachable | "The banking service is temporarily unreachable. Please try again later." |
Any other EnableBankingError | errors.api_error | "A communication error occurred with the bank." |
| Anything else | errors.unexpected | "An unexpected error occurred during synchronization." |
Session-level 401/404 also sets enable_banking_item.status = :requires_update, which flags the connection for user re-authorization. This check is scoped to session-level calls only — per-account 401/404 errors (stale account UID, transient hiccup) are recorded as ordinary sync errors and must not mark the whole connection expired .
promote_session_invalid ensures that if any account in a sync produces a session_invalid error, that message wins over a later, less-severe error — so the top-level sync result always reflects the most actionable problem.
Validation Errors During Paginated Transaction Fetches#
fetch_paginated_transactions has two distinct mid-pagination error handling paths:
1. Continuation Key Mismatch (mid-pagination truncation)#
Some ASPSPs (e.g. certain banks via Enable Banking) issue a continuation_key that their own API then rejects on the next page with a 422 WRONG_REQUEST_PARAMETERS or a 400 (Trade Republic's variant). Rather than discarding all previously fetched pages, the importer :
- Raises normally if the error is anything other than
:validation_erroror:bad_request - Raises normally if the error fires on page 1 (no prior data to fall back on)
- Raises normally if
wrong_transactions_period?is true (a date-range issue, not pagination exhaustion) - Otherwise breaks out of the loop and keeps all transactions collected so far
A capture_pagination_truncation_debug_log entry is written to DebugLogEntry (visible in the /settings/debug UI) recording the pages and transactions kept, so silent data truncations are surfaced for support visibility.
2. Pending Transactions (PDNG) Not Supported#
When fetching pending transactions, some ASPSPs reject the transaction_status=PDNG parameter:
- A 422
:validation_erroris the normal rejection (e.g. ImaginV2 withWRONG_REQUEST_PARAMETERS) - A 400
:bad_requestis Trade Republic's variant
Both are caught and treated as "this ASPSP does not support PDNG" — the importer logs a warning, writes a capture_pdng_unsupported_debug_log entry, and continues with booked transactions only .
Pagination Safety Limits#
Beyond error handling, the paginator enforces two safety checks :
- Page cap:
MAX_PAGINATION_PAGES = 100— raisesPaginationTruncatedErrorif exceeded - Repeated key guard: raises
PaginationTruncatedErrorifcontinuation_keydoes not change between pages
Both are caught and degraded to a warning log + partial result rather than a hard failure .
Key Files#
| File | Purpose |
|---|---|
app/models/provider/enable_banking.rb | HTTP client, handle_response, EnableBankingError class, date-range retry logic |
app/models/enable_banking_item/importer.rb | handle_sync_error, pagination error handling, debug log capture |
config/locales/views/enable_banking_items/en.yml | User-facing error message strings |