we-promise/sure · warning · Provider::Coinstats::Error

CoinStats API request failed: #{e.message}

Error message

CoinStats API request failed: #{e.message}

What it means

Raised by Provider::CoinStats#get_blockchains when the underlying HTTP GET /wallet/blockchains fails with SocketError, Net::OpenTimeout, or Net::ReadTimeout — i.e. the request never completed at the network layer. The original exception is logged ("CoinStats: GET /wallet/blockchains failed: <class>: <msg>") and re-raised as Provider::CoinStats::Error with "CoinStats API request failed: #{e.message}".

Source

Thrown at app/models/provider/coinstats.rb:45

  default_options.merge!({ timeout: 120 }.merge(httparty_ssl_options))

  attr_reader :api_key

  # @param api_key [String] CoinStats API key for authentication
  def initialize(api_key)
    @api_key = api_key
  end

  # Get the list of blockchains supported by CoinStats
  # https://coinstats.app/api-docs/openapi/get-blockchains
  def get_blockchains
    with_provider_response do
      res = self.class.get("#{BASE_URL}/wallet/blockchains", headers: auth_headers)
      handle_response(res)
    end
  rescue SocketError, Net::OpenTimeout, Net::ReadTimeout => e
    Rails.logger.error "CoinStats API: GET /wallet/blockchains failed: #{e.class}: #{e.message}"
    raise Error, "CoinStats API request failed: #{e.message}"
  end

  # Returns blockchain options formatted for select dropdowns
  # @return [Array<Array>] Array of [label, value] pairs sorted alphabetically
  def blockchain_options
    response = get_blockchains

    unless response.success?
      Rails.logger.warn("CoinStats: failed to fetch blockchains: #{response.error&.message}")
      return []
    end

    raw_blockchains = response.data
    items = if raw_blockchains.is_a?(Array)
      raw_blockchains
    elsif raw_blockchains.respond_to?(:dig) && raw_blockchains[:data].is_a?(Array)
      raw_blockchains[:data]
    else

View on GitHub (pinned to e69894adb9)

Solutions

  1. Check the log line for the wrapped class: SocketError = DNS, OpenTimeout = connect, ReadTimeout = server slow/unresponsive — they have different fixes.
  2. Verify basic reachability from the host: curl -I https://api.coinstats.app (fix DNS or firewall if this fails).
  3. If connect/read timeouts recur, pass an explicit timeout to the HTTParty call (e.g. timeout: 30) rather than defaults, and fail fast.
  4. Retry with backoff for transient network blips; the method is a read (GET), so retries are safe.
  5. If it persists only for one host, suspect proxy/egress rules; if it persists for everyone, check CoinStats status and defer the call.

Example fix

# before
res = self.class.get("#{BASE_URL}/wallet/blockchains", headers: auth_headers)

# after
res = self.class.get("#{BASE_URL}/wallet/blockchains", headers: auth_headers, timeout: 30)
# and at the call site:
begin
  options = provider.blockchain_options
rescue Provider::CoinStats::Error => e
  Rails.logger.warn("CoinStats blockchains unavailable: #{e.message}")
  options = []
end
Defensive patterns

Strategy: retry

Validate before calling

require "socket"
TCPSocket.new("api.coinstats.app", 443).close # fail fast if egress/DNS is broken before sync

Type guard

def coinstats_network_error?(err)
  err.is_a?(Provider::CoinStats::Error) && err.message.start_with?("CoinStats API request failed")
end

Try / catch

attempts = 0
begin
  attempts += 1
  options = provider.blockchain_options
rescue Provider::CoinStats::Error => e
  raise if attempts >= 3 || e.message.include?("getaddrinfo")
  sleep(2**attempts)
  retry
else
  options ||= []
end

Prevention

When it happens

Trigger: DNS resolution failure for the CoinStats host (SocketError: "getaddrinfo: Name or service not known"); TCP connect timeout (Net::OpenTimeout) when api.coinstats.app is unreachable or blocked by a firewall; Net::ReadTimeout ("execution expired") when the server accepts the connection but never responds within the HTTParty timeout — e.g. during a CoinStats outage or from a very slow proxy/VPN egress.

Common situations: Containers/servers with broken or flaky resolvers; corporate proxies blocking unknown API hosts; mobile/VPN networks dropping long-lived connections; CoinStats-side incidents; cold-start DNS lookups failing in short-lived serverless-style processes; calling blockchain_options during setup when networking is not yet healthy.

Related errors


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