we-promise/sure · error · Provider::Questrade::Error

unknown

unknown

Error message

Questrade unexpected response (#{response.code})

What it means

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).

Source

Thrown at app/models/provider/questrade.rb:265

      case response.code
      when 200, 201
        JSON.parse(response.body, symbolize_names: true)
      when 400
        capture_response_error("bad_request", response)
        raise Error.new("Questrade bad request (#{response.code})", :bad_request)
      when 401
        raise AuthenticationError.new("Invalid or expired Questrade credentials", :unauthorized)
      when 403
        raise AuthenticationError.new("Access forbidden - check your permissions", :access_forbidden)
      when 404
        raise Error.new("Resource not found", :not_found)
      when 429
        raise RetryableResponseError.new("Questrade rate limit exceeded. Please try again later.", :rate_limited)
      when 500..599
        raise RetryableResponseError.new("Questrade server error (#{response.code}). Please try again later.", :server_error)
      else
        capture_response_error("unexpected_response", response)
        raise Error.new("Questrade unexpected response (#{response.code})", :unknown)
      end
    end
end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Inspect the captured DebugLogEntry (provider_key 'questrade', category 'unexpected_response') for the exact status and body.
  2. Replay the exact URL with curl to see raw headers — especially Location on 3xx to learn where the endpoint moved.
  3. 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.
  4. Report/upgrade if the gem-level client is out of sync with Questrade's current API surface.

Example fix

# before
result = provider.get_balances(account_id: id) # unknown 422 swallowed as :unknown

# after
begin
  result = provider.get_balances(account_id: id)
rescue Provider::Questrade::Error => e
  if e.error_type == :unknown
    DebugLogEntry.capture(category: "questrade", level: "warn",
      message: "Unhandled Questrade status", source: self.class.name,
      provider_key: "questrade", metadata: { item_id: item.id })
  end
  raise
end
Defensive patterns

Strategy: try-catch

Try / catch

begin
  provider.get_balances(account_id: id)
rescue Provider::Questrade::Error => e
  if e.error_type == :unknown
    DebugLogEntry.capture(category: "questrade", level: "warn",
      message: "unhandled status: #{e.message}", source: self.class.name, provider_key: "questrade")
  end
  raise
end

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/b51c89ca7f85cd17. Report an issue: GitHub.