{"record":{"id":"84609373ec6701dd","repo":"we-promise/sure","slug":"parse-error","errorCode":"parse_error","errorMessage":"Failed to parse API response","messagePattern":"Failed to parse API response","errorType":"exception","errorClass":"EnableBankingError","httpStatus":null,"severity":"error","filePath":"app/models/provider/enable_banking.rb","lineNumber":319,"sourceCode":"        raise EnableBankingError.new(\"Failed to fetch data: #{response.code} #{response.message} - #{response.body}\", :fetch_failed, response_data: response_data)\n      end\n    end\n\n    def parse_error_response_body(response)\n      return {} if response.body.blank?\n\n      JSON.parse(response.body, symbolize_names: true)\n    rescue JSON::ParserError\n      { raw_body: response.body.to_s }\n    end\n\n    def parse_response_body(response)\n      return {} if response.body.blank?\n\n      JSON.parse(response.body, symbolize_names: true)\n    rescue JSON::ParserError => e\n      Rails.logger.error \"Enable Banking API: Failed to parse response: #{e.message}\"\n      raise EnableBankingError.new(\"Failed to parse API response\", :parse_error)\n    end\n\n    class EnableBankingError < StandardError\n      attr_reader :error_type, :response_data\n\n      def initialize(message, error_type = :unknown, response_data: nil)\n        super(message)\n        @error_type = error_type\n        @response_data = response_data\n      end\n\n      def wrong_transactions_period?\n        error_type == :validation_error && response_data.is_a?(Hash) && response_data[:error] == \"WRONG_TRANSACTIONS_PERIOD\"\n      end\n\n      def corrected_date_from\n        value = response_data&.dig(:detail, :date_from)\n","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/enable_banking.rb#L301-L337","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"# app/models/provider/enable_banking.rb - parse_response_body\n# before\nJSON.parse(response.body, symbolize_names: true)\n\n# after\nbody = response.body.to_s.delete_prefix(\"\\xEF\\xBB\\xBF\")\nJSON.parse(body, symbolize_names: true)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def enable_banking_parse_error?(error)\n  error.is_a?(Provider::EnableBanking::EnableBankingError) && error.error_type == :parse_error\nend","tryCatchPattern":"begin\n  provider.get_session(session_id: sid)\nrescue Provider::EnableBanking::EnableBankingError => e\n  raise unless e.error_type == :parse_error\n  raise if e.message.include?(\"<html\") # WAF page - retry once, then give up\n  retry # transient truncation\nend","preventionTips":["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"],"tags":["enable-banking","json","parse-error","gateway","response-body"],"backgroundTag":"invalid-json-response","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}