we-promise/sure · error · Provider::Simplefin::SimplefinError

claim_failed

claim_failed

Error message

Failed to claim access URL: #{response.code} #{response.message}

What it means

Raised by Provider::Simplefin#claim_access_url when the claim POST returns any status other than 200 or 403, with error_type :claim_failed. The message embeds the HTTP status and HTTParty message. Note the claim runs with max_retries: 1 and no backoff, so network resilience here is minimal by design (claim should be fast).

Source

Thrown at app/models/provider/simplefin.rb:50

  def claim_access_url(setup_token)
    # Decode the base64 setup token to get the claim URL
    claim_url = Base64.decode64(setup_token)

    # Use retry logic for transient network failures during token claim
    # Claim should be fast; keep request-path latency bounded.
    # Use self.class.post to inherit class-level SSL and timeout defaults
    response = with_retries("POST /claim", max_retries: 1, backoff: false) do
      self.class.post(claim_url, timeout: 15)
    end

    case response.code
    when 200
      # The response body contains the access URL with embedded credentials
      response.body.strip
    when 403
      raise SimplefinError.new("Setup token may be compromised, expired, or already used", :token_compromised)
    else
      raise SimplefinError.new("Failed to claim access URL: #{response.code} #{response.message}", :claim_failed)
    end
  end

  def get_accounts(access_url, start_date: nil, end_date: nil, pending: nil)
    # Build query parameters
    query_params = {}

    # SimpleFin expects Unix timestamps for dates
    if start_date
      start_timestamp = start_date.to_time.to_i
      query_params["start-date"] = start_timestamp.to_s
    end

    if end_date
      end_timestamp = end_date.to_time.to_i
      query_params["end-date"] = end_timestamp.to_s
    end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Decode the token and confirm it yields a valid https claim URL before calling (Base64.decode64(token))
  2. Check the SimpleFin bridge status page for outages
  3. Retry with a newly generated token if the current one may be malformed
  4. Handle 5xx claim failures with a caller-side retry schedule (the client retries only once, without backoff)
Defensive patterns

Strategy: validation

Validate before calling

require "uri"

def claim_url_from_token(setup_token)
  decoded = Base64.decode64(setup_token.to_s)
  uri = URI.parse(decoded)
  uri.is_a?(URI::HTTPS) ? uri : nil
rescue URI::InvalidURIError, ArgumentError
  nil
end

raise ArgumentError, "invalid setup token" unless claim_url_from_token(setup_token)

Type guard

def simplefin_claim_failed?(error)
  error.is_a?(Provider::Simplefin::SimplefinError) && error.error_type == :claim_failed
end

Try / catch

begin
  access_url = client.claim_access_url(setup_token)
rescue Provider::Simplefin::SimplefinError => e
  raise unless e.error_type == :claim_failed
  ClaimRetryJob.perform_in(5.minutes, user.id) if e.message.match?(/\b5\d\d\b/)
end

Prevention

When it happens

Trigger: Setup token base64-decodes to something that is not a valid claim URL (404/hostname failure); SimpleFin bridge cluster down or returning 5xx; redirect/misconfigured token from a nonstandard bridge.

Common situations: Hand-edited or truncated base64 token decoding to garbage; SimpleFin bridge maintenance window; tokens issued by a self-hosted bridge whose URL the app cannot reach.

Related errors


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