we-promise/sure · error · EnableBankingError

timeout

timeout

Error message

Request timeout from Enable Banking API

What it means

Raised by Provider::EnableBanking#handle_response when https://api.enablebanking.com returns HTTP 408. Enable Banking is an open-banking aggregator that proxies each request to the user's bank (ASPSP); a 408 means the upstream bank or the aggregator gateway abandoned the request server-side before responding. It is not the local HTTParty timeout (120s) - that surfaces as :request_failed via the SocketError/Net timeout rescues.

Source

Thrown at app/models/provider/enable_banking.rb:293

    end

    def handle_response(response)
      case response.code
      when 200, 201
        parse_response_body(response)
      when 204
        {}
      when 400
        response_data = parse_error_response_body(response)
        raise EnableBankingError.new("Bad request to Enable Banking API: #{response.body}", :bad_request, response_data: response_data)
      when 401
        raise EnableBankingError.new("Invalid credentials or expired JWT", :unauthorized)
      when 403
        raise EnableBankingError.new("Access forbidden - check your application permissions", :access_forbidden)
      when 404
        raise EnableBankingError.new("Resource not found", :not_found)
      when 408
        raise EnableBankingError.new("Request timeout from Enable Banking API", :timeout)
      when 422
        response_data = parse_response_body(response)
        raise EnableBankingError.new("Validation error from Enable Banking API: #{response.body}", :validation_error, response_data: response_data)
      when 429
        raise EnableBankingError.new("Rate limit exceeded. Please try again later.", :rate_limited)
      else
        response_data = parse_error_response_body(response)
        raise EnableBankingError.new("Failed to fetch data: #{response.code} #{response.message} - #{response.body}", :fetch_failed, response_data: response_data)
      end
    end

    def parse_error_response_body(response)
      return {} if response.body.blank?

      JSON.parse(response.body, symbolize_names: true)
    rescue JSON::ParserError
      { raw_body: response.body.to_s }
    end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Retry the same call on the next sync cycle or after short backoff (e.g. 30s, 2m) - most 408s are transient upstream slowness, not a config problem
  2. Narrow the transactions window: fetch in smaller date ranges and page with continuation_key instead of one huge request
  3. If only one institution fails, check the Enable Banking status/health endpoint and that ASPSP's availability before touching credentials
  4. Branch on error_type == :timeout in the caller so the sync is retried later rather than flagged as an auth or consent failure

Example fix

// before
provider.get_account_transactions(account_id: id, date_from: 3.years.ago, date_to: Date.current)

// after
begin
  provider.get_account_transactions(account_id: id, date_from: date_from, date_to: date_to)
rescue Provider::EnableBanking::EnableBankingError => e
  raise if e.error_type != :timeout
  RetryableSync.schedule(account, wait: 2.minutes) # retry next cycle with smaller range
end
Defensive patterns

Strategy: retry

Type guard

def enable_banking_timeout?(error)
  error.is_a?(Provider::EnableBanking::EnableBankingError) && error.error_type == :timeout
end

Try / catch

begin
  provider.get_account_transactions(account_id: id, date_from: from, date_to: to)
rescue Provider::EnableBanking::EnableBankingError => e
  if e.error_type == :timeout
    RetryableSync.schedule(account, wait: 2.minutes) # transient upstream slowness
  else
    raise
  end
end

Prevention

When it happens

Trigger: GET /accounts/{id}/transactions with a wide date_from/date_to range against a slow ASPSP; the first history sync of a newly connected account; calls made while the target bank is in a maintenance window; hammering the same session with concurrent sync jobs so the gateway queues and times out.

Common situations: Initial sync pulling years of transactions in one call, one chronically slow bank among a user's connections, transient aggregator congestion, or dev and prod environments sharing one application_id and exhausting gateway capacity simultaneously.

Understand the failure class

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/e0feaa68840a8f0d. Report an issue: GitHub.