{"record":{"id":"b51c89ca7f85cd17","repo":"we-promise/sure","slug":"unknown-b51c89","errorCode":"unknown","errorMessage":"Questrade unexpected response (#{response.code})","messagePattern":"Questrade unexpected response \\(#(.+?)\\)","errorType":"exception","errorClass":"Provider::Questrade::Error","httpStatus":null,"severity":"error","filePath":"app/models/provider/questrade.rb","lineNumber":265,"sourceCode":"      case response.code\n      when 200, 201\n        JSON.parse(response.body, symbolize_names: true)\n      when 400\n        capture_response_error(\"bad_request\", response)\n        raise Error.new(\"Questrade bad request (#{response.code})\", :bad_request)\n      when 401\n        raise AuthenticationError.new(\"Invalid or expired Questrade 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 RetryableResponseError.new(\"Questrade rate limit exceeded. Please try again later.\", :rate_limited)\n      when 500..599\n        raise RetryableResponseError.new(\"Questrade server error (#{response.code}). Please try again later.\", :server_error)\n      else\n        capture_response_error(\"unexpected_response\", response)\n        raise Error.new(\"Questrade unexpected response (#{response.code})\", :unknown)\n      end\n    end\nend\n","sourceCodeStart":247,"sourceCodeEnd":269,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/questrade.rb#L247-L269","documentation":"The catch-all branch of Provider::Questrade#handle_response for any status outside 200/201/400/401/403/404/429/5xx — e.g. 202/204 with an unexpected body, 3xx redirects, or unusual 4xx codes (405, 409, 410, 422). capture_response_error logs the code and first 1000 chars of the body to the /settings/debug channel before raising Error(:unknown).","triggerScenarios":"A 204 No Content from an endpoint where the client expects JSON (handle_response would parse empty body on 200 but a 204 lands here); a redirect because api_server responded with a moved endpoint; new 4xx semantics Questrade introduced that the case statement does not enumerate.","commonSituations":"Questrade API version changes adding 422 validation responses; proxies returning 502 is covered (5xx) but 502-with-3xx-redirect chains are not; endpoints returning 202 for async processing hitting synchronous client code.","solutions":["Inspect the captured DebugLogEntry (provider_key 'questrade', category 'unexpected_response') for the exact status and body.","Replay the exact URL with curl to see raw headers — especially Location on 3xx to learn where the endpoint moved.","If a legitimate new status appears repeatedly (e.g. 422), add an explicit when branch to handle_response instead of relying on the catch-all.","Report/upgrade if the gem-level client is out of sync with Questrade's current API surface."],"exampleFix":"# before\nresult = provider.get_balances(account_id: id) # unknown 422 swallowed as :unknown\n\n# after\nbegin\n  result = provider.get_balances(account_id: id)\nrescue Provider::Questrade::Error => e\n  if e.error_type == :unknown\n    DebugLogEntry.capture(category: \"questrade\", level: \"warn\",\n      message: \"Unhandled Questrade status\", source: self.class.name,\n      provider_key: \"questrade\", metadata: { item_id: item.id })\n  end\n  raise\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  provider.get_balances(account_id: id)\nrescue Provider::Questrade::Error => e\n  if e.error_type == :unknown\n    DebugLogEntry.capture(category: \"questrade\", level: \"warn\",\n      message: \"unhandled status: #{e.message}\", source: self.class.name, provider_key: \"questrade\")\n  end\n  raise\nend","preventionTips":["Check /settings/debug for the captured status/body before guessing.","When a new status recurs (e.g. 422), add an explicit branch to handle_response instead of living on the catch-all."],"tags":["questrade","unexpected-status","catch-all","brokerage-api"],"backgroundTag":"unexpected-http-status","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}