we-promise/sure · error · Provider::Snaptrade::ApiError
SnapTrade API error (#{operation}): HTTP #{response.status}
Error message
SnapTrade API error (#{operation}): HTTP #{response.status} What it means
The fallback branch of Provider::Snaptrade.handle_response: any HTTP status other than 2xx, 401/403, 429, and 500-599 raises this generic ApiError with the operation name and status. The error object exposes status_code and response_body for diagnosis; 400-class and 404-class responses land here.
Source
Thrown at app/models/provider/snaptrade.rb:395
JSON.parse(response.body)
rescue JSON::ParserError
raise ApiError.new("SnapTrade API error (#{operation}): invalid JSON response",
status_code: response.status, response_body: response.body)
end
else
Rails.logger.error("SnapTrade API error (#{operation}): #{response.status}")
case response.status
when 401, 403
mark_requires_update!
raise AuthenticationError, "Authentication failed (#{operation}): HTTP #{response.status}"
when 429
raise ApiError.new("Rate limit exceeded. Please try again later.",
status_code: response.status, response_body: response.body)
when 500..599
raise ApiError.new("SnapTrade server error (#{response.status}). Please try again later.",
status_code: response.status, response_body: response.body)
else
raise ApiError.new("SnapTrade API error (#{operation}): HTTP #{response.status}",
status_code: response.status, response_body: response.body)
end
end
end
def api_connection
@api_connection ||= Faraday.new do |faraday|
faraday.options.timeout = 30
faraday.options.open_timeout = 10
end
end
def with_retries(operation_name, max_retries: MAX_RETRIES)
retries = 0
begin
yield
rescue Faraday::TimeoutError, Faraday::ConnectionFailed, Errno::ECONNRESET, Errno::ETIMEDOUT => eView on GitHub (pinned to e69894adb9)
Solutions
- Inspect err.status_code and err.response_body - the body usually names the invalid parameter or missing resource
- 404: re-fetch the account list for the connection - the account may have been closed or re-keyed on re-link
- 400: validate request params (date formats, account_id shape) against the current SnapTrade API docs for that operation
- After a SnapTrade API version change, audit each operation name in the message against the new endpoint signatures
Defensive patterns
Strategy: try-catch
Validate before calling
def valid_snaptrade_account_id?(id)
id.is_a?(String) && id.match?(/\A[0-9a-f-]{36}\z/i) # adjust to SnapTrade's id shape
end Try / catch
begin
snaptrade.get_positions(account_id: id)
rescue Provider::Snaptrade::ApiError => e
if [400, 404, 410].include?(e.status_code)
refresh_account_list!(e.response_body) # stale ids: re-sync from source of truth
else
raise
end
end Prevention
- Always branch on e.status_code / e.response_body rather than the formatted message
- Re-fetch the account list when a stored account_id starts 404ing (user re-linked)
- Validate request params (ids, dates) against current SnapTrade docs after gem/API upgrades
When it happens
Trigger: Calling a SnapTrade endpoint with a bad parameter (400), a deleted/unknown account_id (404), a removed endpoint after an API version bump (404/410), or any status the case statement does not special-case.
Common situations: Stored SnapTrade account reference stale after the user re-linked the connection (old account_id now 404s); request parameter changes after upgrading the snaptrade gem/API version; malformed query params (bad date format in startDate).
Related errors
- Network error after #{max_retries} retries: #{e.message}
- SnapTrade API error (#{operation}): invalid JSON response
- Lunchflow provider is not configured
- pagination_error
- request_failed
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/70f995af13c62280.
Report an issue: GitHub.