we-promise/sure · error · EnableBankingError
parse_error
parse_error
Error message
Failed to parse API response
What it means
Raised by parse_response_body when a 2xx response body exists but is not valid JSON. Blank bodies are fine; anything else - an HTML WAF/challenge page, a truncated body, a BOM-prefixed payload - raises JSON::ParserError, which is logged and re-raised as EnableBankingError(:parse_error). Note the asymmetry: error responses use the lenient parse_error_response_body (raw_body fallback), success responses use this strict one.
Source
Thrown at app/models/provider/enable_banking.rb:319
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)
end
class EnableBankingError < StandardError
attr_reader :error_type, :response_data
def initialize(message, error_type = :unknown, response_data: nil)
super(message)
@error_type = error_type
@response_data = response_data
end
def wrong_transactions_period?
error_type == :validation_error && response_data.is_a?(Hash) && response_data[:error] == "WRONG_TRANSACTIONS_PERIOD"
end
def corrected_date_from
value = response_data&.dig(:detail, :date_from)
View on GitHub (pinned to e69894adb9)
Solutions
- Check the preceding Rails log line 'Enable Banking API: Failed to parse response:' for the JSON::ParserError detail (unexpected token at...) - HTML bodies are obvious there
- Retry once after a short delay: interstitials and truncation are usually transient
- Strip a UTF-8 BOM before parsing and capture the raw body in the error/DebugLogEntry so the payload is diagnosable
- If persistent, verify nothing between the app and the API rewrites responses (proxy, SSL inspection)
Example fix
# app/models/provider/enable_banking.rb - parse_response_body
# before
JSON.parse(response.body, symbolize_names: true)
# after
body = response.body.to_s.delete_prefix("\xEF\xBB\xBF")
JSON.parse(body, symbolize_names: true) Defensive patterns
Strategy: try-catch
Type guard
def enable_banking_parse_error?(error) error.is_a?(Provider::EnableBanking::EnableBankingError) && error.error_type == :parse_error end
Try / catch
begin
provider.get_session(session_id: sid)
rescue Provider::EnableBanking::EnableBankingError => e
raise unless e.error_type == :parse_error
raise if e.message.include?("<html") # WAF page - retry once, then give up
retry # transient truncation
end Prevention
- Strip UTF-8 BOM from response bodies before JSON.parse
- Alert when parse_error clusters - it usually means a proxy/WAF started rewriting responses
- Keep the failure log line (it captures the JSON::ParserError detail) searchable
- Verify no SSL-inspection proxy sits between the app and api.enablebanking.com
When it happens
Trigger: An edge proxy/CDN in front of api.enablebanking.com returns a 200 HTML interstitial; the connection drops mid-body leaving truncated JSON; the payload starts with a UTF-8 BOM so JSON.parse rejects it; a middleware maintenance page returned with status 200.
Common situations: Cloudflare-style bot challenges hitting server-to-server traffic, flaky NAT dropping long transaction payloads, a misconfigured corporate proxy injecting an HTML banner, BOM added by a response-transforming middleware.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- bad_response
- Could not save that passkey or security key. Please try agai
- request_failed
- invalid_certificate
- bad_request
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/84609373ec6701dd.
Report an issue: GitHub.