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]
elseView on GitHub (pinned to e69894adb9)
Solutions
- Check the log line for the wrapped class: SocketError = DNS, OpenTimeout = connect, ReadTimeout = server slow/unresponsive — they have different fixes.
- Verify basic reachability from the host: curl -I https://api.coinstats.app (fix DNS or firewall if this fails).
- If connect/read timeouts recur, pass an explicit timeout to the HTTParty call (e.g. timeout: 30) rather than defaults, and fail fast.
- Retry with backoff for transient network blips; the method is a read (GET), so retries are safe.
- 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
- Add an explicit timeout: option to CoinStats HTTParty calls instead of relying on defaults.
- Ensure the host can resolve and reach api.coinstats.app (DNS, proxy, firewall) before scheduling syncs.
- blockchain_options already degrades to [] — keep call sites rendering empty-with-warning rather than raising.
- Retry only transient classes: ReadTimeout/OpenTimeout; fix DNS first for SocketError.
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.