{"record":{"id":"c43132164585ea40","repo":"we-promise/sure","slug":"bad-response","errorCode":"bad_response","errorMessage":"Invalid JSON in response: #{e.message}","messagePattern":"Invalid JSON in response: #(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/models/provider/indexa_capital.rb","lineNumber":198,"sourceCode":"          username: username,\n          document: document,\n          password: password\n        }.to_json\n      )\n      payload = handle_response(response)\n      jwt = payload[:token]\n      raise AuthenticationError.new(\"Authentication token missing in response\", :unauthorized) if jwt.blank?\n\n      jwt\n    end\n\n    def handle_response(response)\n      case response.code\n      when 200, 201\n        begin\n          JSON.parse(response.body, symbolize_names: true)\n        rescue JSON::ParserError => e\n          raise Error.new(\"Invalid JSON in response: #{e.message}\", :bad_response)\n        end\n      when 400\n        Rails.logger.error \"IndexaCapital API: Bad request - #{response.body}\"\n        raise Error.new(\"Bad request: #{response.body}\", :bad_request)\n      when 401\n        raise AuthenticationError.new(\"Invalid credentials\", :unauthorized)\n      when 403\n        raise AuthenticationError.new(\"Access forbidden - check your permissions\", :access_forbidden)\n      when 404\n        raise Error.new(\"Resource not found\", :not_found)\n      when 429\n        raise Error.new(\"Rate limit exceeded. Please try again later.\", :rate_limited)\n      when 500..599\n        raise Error.new(\"IndexaCapital server error (#{response.code}). Please try again later.\", :server_error)\n      else\n        Rails.logger.error \"IndexaCapital API: Unexpected response - Code: #{response.code}, Body: #{response.body}\"\n        raise Error.new(\"Unexpected error: #{response.code} - #{response.body}\", :unknown)\n      end","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/indexa_capital.rb#L180-L216","documentation":"A 200/201 response from api.indexacapital.com whose body is not valid JSON (JSON::ParserError), re-raised as Error(:bad_response) with the parser's message embedded. The raw body itself is not included in the error - only e.message's parser detail - so diagnosis leans on the message shape ('unexpected token at ...' usually means HTML).","triggerScenarios":"A WAF/CDN in front of the API returns a 200 HTML challenge or banner page; the connection drops mid-body leaving truncated JSON; an SSL-inspection proxy rewrites responses; a maintenance interstitial served with 200.","commonSituations":"Bot-challenge pages hitting datacenter IPs, corporate proxies injecting HTML notices, flaky networking truncating large /portfolio responses.","solutions":["Match on the parser detail in e.message: 'unexpected token at \\'<\\'' almost always means an HTML page came back","Retry once after a short delay - interstitials are typically one-shot","Add the raw body to the error message (it is currently dropped) and capture it via DebugLogEntry for support","Verify no intermediary (proxy, SSL inspection) sits between the app and api.indexacapital.com"],"exampleFix":"# app/models/provider/indexa_capital.rb - handle_response\n# before\nrescue JSON::ParserError => e\n  raise Error.new(\"Invalid JSON in response: #{e.message}\", :bad_response)\n\n# after\nrescue JSON::ParserError => e\n  raise Error.new(\"Invalid JSON in response: #{e.message} - body: #{response.body.to_s[0, 200]}\", :bad_response)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def indexa_bad_response?(error)\n  error.is_a?(Provider::IndexaCapital::Error) && error.error_type == :bad_response\nend","tryCatchPattern":"begin\n  provider.list_accounts\nrescue Provider::IndexaCapital::Error => e\n  raise unless e.error_type == :bad_response\n  retry if (retries += 1) <= 1 && e.message.include?(\"<\") # HTML interstitial: one retry\n  raise\nend","preventionTips":["Treat 'unexpected token at <' in the message as an HTML page, not bad data","Patch the provider to embed the raw body (first ~200 chars) in the error for diagnosability","Retry once - interstitials and truncation are usually single-shot","Keep intermediary proxies/SSL-inspection off the path to api.indexacapital.com"],"tags":["indexa-capital","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"}