we-promise/sure · error · EnableBankingError
fetch_failed
fetch_failed
Error message
Failed to fetch data: #{response.code} #{response.message} - #{response.body} What it means
The catch-all branch of handle_response: any status not in 204/400/401/403/404/408/422/429 lands here - typically 5xx from the aggregator or upstream bank, but also 3xx redirects and unmapped 4xx (409, 410, 418...). The message embeds response.code, response.message and the raw body; response_data comes from the lenient parser, so a non-JSON body yields { raw_body: "..." } instead of a secondary parse error.
Source
Thrown at app/models/provider/enable_banking.rb:301
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
def parse_response_body(response)
return {} if response.body.blank?
JSON.parse(response.body, symbolize_names: true)
rescue JSON::ParserError => e
Rails.logger.error "Enable Banking API: Failed to parse response: #{e.message}"
raise EnableBankingError.new("Failed to parse API response", :parse_error)View on GitHub (pinned to e69894adb9)
Solutions
- Read the embedded status: parse the leading number in the message or use e.response_data - 5xx means retry later, 3xx/4xx means investigate the request
- Treat 5xx occurrences as transient: reschedule the sync, do not invalidate credentials or consent
- Capture the full response_data via DebugLogEntry so support can correlate with the aggregator's logs
- If every call fails with the same odd status, diff the request path/headers against the current Enable Banking API docs
Example fix
// before
rescue Provider::EnableBanking::EnableBankingError => e
notify_error(e) # every failure paged on-call
// after
rescue Provider::EnableBanking::EnableBankingError => e
if e.error_type == :fetch_failed && e.message[/\AFailed to fetch data: (\d{3})/, 1].to_i >= 500
RetryableSync.schedule(account, wait: 10.minutes)
else
notify_error(e)
end
end Defensive patterns
Strategy: try-catch
Type guard
def enable_banking_fetch_failed?(error)
error.is_a?(Provider::EnableBanking::EnableBankingError) && error.error_type == :fetch_failed
end
def fetch_failed_status(error)
error.message[/\AFailed to fetch data: (\d{3})/, 1].to_i
end Try / catch
begin
provider.get_account_balances(account_id: id)
rescue Provider::EnableBanking::EnableBankingError => e
raise unless e.error_type == :fetch_failed
status = e.message[/\AFailed to fetch data: (\d{3})/, 1].to_i
if status >= 500
RetryableSync.schedule(account, wait: 15.minutes) # upstream/aggregator outage
else
DebugLogEntry.capture(category: :enable_banking, level: :error,
message: e.message, metadata: e.response_data || {})
raise
end
end Prevention
- Always branch on the embedded status before deciding retry vs alert
- Persist e.response_data (including raw_body) in the debug log for support correlation
- Treat 5xx as transient and 3xx as a config/BASE_URL smell
- Alert only when the same unmapped status repeats across cycles
When it happens
Trigger: Enable Banking gateway returns 500/502/503 when an ASPSP integration is down; an endpoint moves and the gateway 301-redirects; an unmapped 4xx like 409 on a duplicate session creation; a proxy in front of the API returns an odd status.
Common situations: Single-bank outages surfacing as aggregator 5xx, deploy windows at Enable Banking, BASE_URL drift if the provider version changes paths, or HTML error pages from an edge proxy.
Related errors
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/32e44d34e81f4eb0.
Report an issue: GitHub.