we-promise/sure · warning · Provider::Trading212::RateLimitError

Trading 212 rate limit exceeded. Please wait before retrying

Error message

Trading 212 rate limit exceeded. Please wait before retrying.

What it means

Provider::Trading212::RateLimitError raised in handle_response when the Trading 212 API answers HTTP 429. Trading 212 enforces roughly 1 request/second per connection and tighter limits on history endpoints (the client even sleeps 10s between history pages), so bursts trigger this response.

Source

Thrown at app/models/provider/trading212.rb:137

      items
    end

    def extract_cursor(next_page_path)
      uri = URI.parse("https://placeholder#{next_page_path}")
      params = URI.decode_www_form(uri.query.to_s).to_h
      params["cursor"]
    rescue URI::InvalidURIError
      nil
    end

    def handle_response(response)
      case response.code
      when 200, 201
        response.parsed_response
      when 401, 403
        raise AuthenticationError, "Trading 212 authentication failed (#{response.code}). Check your API key."
      when 429
        raise RateLimitError, "Trading 212 rate limit exceeded. Please wait before retrying."
      else
        raise ApiError.new(
          "Trading 212 API error (status #{response.code})",
          status_code: response.code,
          response_body: response.body
        )
      end
    end

    def with_retries(label, max_retries: 3)
      attempt = 0
      begin
        attempt += 1
        yield
      rescue *RETRYABLE_ERRORS => e
        raise if attempt >= max_retries
        delay = [ 2**attempt, 30 ].min
        DebugLogEntry.capture(

View on GitHub (pinned to e69894adb9)

Solutions

  1. Wait before retrying: back off at least 1–10 seconds (history endpoints need ~10s between calls) and use exponential backoff
  2. Serialize requests per API key (a mutex or single worker) so concurrent jobs don't burst past ~1 req/s
  3. Rescue Provider::Trading212::RateLimitError separately from AuthenticationError and schedule a delayed retry (e.g. retry_job wait: 30) instead of failing the sync
  4. Reduce page volume by keeping the built-in PAGE_LIMIT/MAX_PAGES pagination rather than fetching unpaginated

Example fix

// before
begin
  client.fetch_account_summary
rescue Provider::Trading212::Error
  retry # tight loop -> 429 loop
end

// after
begin
  client.fetch_account_summary
rescue Provider::Trading212::RateLimitError
  sleep 30
  retry
rescue Provider::Trading212::AuthenticationError
  raise # do not retry auth failures
end
Defensive patterns

Strategy: retry

Try / catch

begin
  client.fetch_positions
rescue Provider::Trading212::RateLimitError
  sleep 30 * attempt # exponential-ish backoff, cap attempts
  retry if (attempt += 1) <= 3
rescue Provider::Trading212::AuthenticationError
  raise
end

Prevention

When it happens

Trigger: Calling fetch_account_summary/fetch_positions in quick succession; parallel jobs syncing the same or multiple Trading 212 accounts; ignoring the pacing in fetch_all_pages (which sleeps 10s per page because history endpoints allow ~6 req/min); an immediate retry after a previous request.

Common situations: Background jobs overlapping for different users on the same API key; manual console testing while a sync job runs; retry logic without backoff hammering the API.

Related errors


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