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: acct

View on GitHub (pinned to e69894adb9)

Solutions

  1. Retry later with backoff - treat :server_error as transient and never invalidate credentials because of it
  2. Schedule the retry on the next sync cycle rather than hammering inline
  3. Capture DebugLogEntry with the status for pattern analysis (which endpoint, which hours)
  4. 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

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.