{"record":{"id":"7e8799476a691498","repo":"we-promise/sure","slug":"not-found-7e8799","errorCode":"not_found","errorMessage":"Resource not found","messagePattern":"Resource not found","errorType":"exception","errorClass":"EnableBankingError","httpStatus":404,"severity":"warning","filePath":"app/models/provider/enable_banking.rb","lineNumber":291,"sourceCode":"        \"Accept\" => \"application/json\"\n      }\n    end\n\n    def handle_response(response)\n      case response.code\n      when 200, 201\n        parse_response_body(response)\n      when 204\n        {}\n      when 400\n        response_data = parse_error_response_body(response)\n        raise EnableBankingError.new(\"Bad request to Enable Banking API: #{response.body}\", :bad_request, response_data: response_data)\n      when 401\n        raise EnableBankingError.new(\"Invalid credentials or expired JWT\", :unauthorized)\n      when 403\n        raise EnableBankingError.new(\"Access forbidden - check your application permissions\", :access_forbidden)\n      when 404\n        raise EnableBankingError.new(\"Resource not found\", :not_found)\n      when 408\n        raise EnableBankingError.new(\"Request timeout from Enable Banking API\", :timeout)\n      when 422\n        response_data = parse_response_body(response)\n        raise EnableBankingError.new(\"Validation error from Enable Banking API: #{response.body}\", :validation_error, response_data: response_data)\n      when 429\n        raise EnableBankingError.new(\"Rate limit exceeded. Please try again later.\", :rate_limited)\n      else\n        response_data = parse_error_response_body(response)\n        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","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/enable_banking.rb#L273-L309","documentation":"Raised by Provider::EnableBanking#handle_response on HTTP 404: the referenced session or account does not exist (anymore). The most common real cause is PSD2 consent expiry — sessions die when the bank consent ends (typically 90 days, matching maximum_consent_validity) — so a previously working session_id or account uid starts 404ing.","triggerScenarios":"get_session/get_account_details/get_account_balances/get_account_transactions called with a session whose consent expired or was revoked at the bank; a session deleted via delete_session; a mistyped account uid or one from another environment.","commonSituations":"Syncs scheduled past the 90-day consent window, users revoking consent at their bank, stale connection records surviving after disconnect.","solutions":["Treat it as terminal for the connection: mark the linked account as needing re-authorization and stop retrying the sync","Distinguish from :request_failed — 404 means the API answered 'gone', not that the network failed","Verify the session_id/account uid values being passed match what create_session/get_session originally returned","Track consent expiry (access.valid_until negotiated at start_authorization) and prompt re-auth before the 404s start"],"exampleFix":"# before\ntxns = client.get_account_transactions(account_id: uid, date_from: from)\n\n# after\nbegin\n  txns = client.get_account_transactions(account_id: uid, date_from: from)\nrescue Provider::EnableBanking::EnableBankingError => e\n  raise unless e.error_type == :not_found\n  connection.update!(status: \"reauth_required\")\n  txns = { transactions: [] }\nend","handlingStrategy":"fallback","validationCode":"def eb_session_alive?(client, session_id)\n  client.get_session(session_id: session_id) && true\nrescue Provider::EnableBanking::EnableBankingError => e\n  e.error_type != :not_found\nend","typeGuard":"def eb_not_found?(error)\n  error.is_a?(Provider::EnableBanking::EnableBankingError) && error.error_type == :not_found\nend","tryCatchPattern":"begin\n  txns = client.get_account_transactions(account_id: uid, date_from: from)\nrescue Provider::EnableBanking::EnableBankingError => e\n  raise unless e.error_type == :not_found\n  connection.update!(status: \"reauth_required\") # consent expired/revoked — no retry\n  txns = { transactions: [] }\nend","preventionTips":["Track consent valid_until negotiated at start_authorization and prompt re-auth before expiry (~90 days)","Handle 404 as an expected consent lifecycle event with a reauth flow, not an error page","Only pass session/account ids returned by create_session/get_session","After delete_session, immediately clear local ids so later syncs don't query ghosts"],"tags":["enable-banking","http-404","consent-expiry","psd2","sync"],"backgroundTag":"http-404-not-found","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}