we-promise/sure · error · Error
server_error
server_error
Error message
IndexaCapital server error (#{response.code}). Please try again later. What it means
Any 500..599 from api.indexacapital.com maps to Error(:server_error) with the status code embedded. Important nuance: with_retries only retries transport exceptions - a 5xx HTTP response is returned normally by HTTParty and raised immediately by handle_response, so the provider does NOT auto-retry these even though they are usually transient.
Source
Thrown at app/models/provider/indexa_capital.rb:212
when 200, 201
begin
JSON.parse(response.body, symbolize_names: true)
rescue JSON::ParserError => e
raise Error.new("Invalid JSON in response: #{e.message}", :bad_response)
end
when 400
Rails.logger.error "IndexaCapital API: Bad request - #{response.body}"
raise Error.new("Bad request: #{response.body}", :bad_request)
when 401
raise AuthenticationError.new("Invalid 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 Error.new("Rate limit exceeded. Please try again later.", :rate_limited)
when 500..599
raise Error.new("IndexaCapital server error (#{response.code}). Please try again later.", :server_error)
else
Rails.logger.error "IndexaCapital API: Unexpected response - Code: #{response.code}, Body: #{response.body}"
raise Error.new("Unexpected error: #{response.code} - #{response.body}", :unknown)
end
end
# Extract accounts array from /users/me response
# API returns: { accounts: [{ account_number: "ABC12345", type: "mutual", status: "active", ... }] }
def extract_accounts(user_data)
accounts = user_data[:accounts] || []
accounts.map do |acct|
{
account_number: acct[:account_number],
name: account_display_name(acct),
type: acct[:type],
status: acct[:status],
currency: "EUR",
raw: acctView on GitHub (pinned to e69894adb9)
Solutions
- Retry later with backoff - treat :server_error as transient and never invalidate credentials because of it
- Schedule the retry on the next sync cycle rather than hammering inline
- Capture DebugLogEntry with the status for pattern analysis (which endpoint, which hours)
- If you want automatic handling, add a 5xx-aware retry around the call (see exampleFix) since with_retries will not do it
Example fix
# before provider.list_accounts # after retries = 0 begin provider.list_accounts rescue Provider::IndexaCapital::Error => e retries += 1 retry if e.error_type == :server_error && retries <= 3 && sleep(2**retries) raise end
Defensive patterns
Strategy: retry
Type guard
def indexa_server_error?(error) error.is_a?(Provider::IndexaCapital::Error) && error.error_type == :server_error end
Try / catch
retries = 0 begin provider.list_accounts rescue Provider::IndexaCapital::Error => e retries += 1 retry if e.error_type == :server_error && retries <= 3 && sleep(2**retries) RetryableSync.schedule(account, wait: 30.minutes) if retries > 3 raise end
Prevention
- Know that with_retries only covers transport errors - 5xx needs your own retry wrapper
- Never invalidate credentials on :server_error
- Track which endpoint/hour 5xxs cluster to schedule around Indexa's busy windows
- Cap retries and hand off to the scheduler instead of looping inline
When it happens
Trigger: Indexa outage or deployment window; upstream database issues returning 500/503 on /users/me; load-shedding 503s during market-close spikes on /accounts/{n}/performance.
Common situations: Spanish market hours concentration (many users polling performance after close), Indexa maintenance windows, transient 502/504 from their gateway.
Related errors
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/7aee135fd9baf442.
Report an issue: GitHub.