we-promise/sure · error · Provider::BinancePublic::Error

Unsupported Binance ticker: #{symbol}

Error message

Unsupported Binance ticker: #{symbol}

What it means

Raised by Provider::BinancePublic#fetch_security_info when parse_ticker(symbol) returns nil — the symbol does not match the ticker grammar this provider supports (crypto base/quote pairs recognized around parse_ticker at binance_public.rb:324). It is raised as Provider::BinancePublic::Error, aborting the SecurityInfo lookup before any HTTP call.

Source

Thrown at app/models/provider/binance_public.rb:156

          name: base,
          # Brandfetch /crypto/{base} URL — unknown coins (rare) will 400 and
          # render as a broken img in the dropdown; same tradeoff as stocks
          # with obscure tickers. `::Security` reaches the AR model —
          # unqualified `Security` here resolves to the Data value-object
          # from SecurityConcept.
          logo_url: ::Security.brandfetch_crypto_url(base),
          exchange_operating_mic: BINANCE_MIC,
          country_code: nil,
          currency: display_currency
        )
      end
    end
  end

  def fetch_security_info(symbol:, exchange_operating_mic:)
    with_provider_response do
      parsed = parse_ticker(symbol)
      raise Error, "Unsupported Binance ticker: #{symbol}" if parsed.nil?

      # logo_url is intentionally nil — crypto logos are set at save time by
      # Security#generate_logo_url_from_brandfetch via the /crypto/{base}
      # route, not returned from this provider.
      links = parsed[:binance_pair] ? "https://www.binance.com/en/trade/#{parsed[:binance_pair]}" : nil

      SecurityInfo.new(
        symbol: symbol,
        name: parsed[:base],
        links: links,
        logo_url: nil,
        description: nil,
        kind: "crypto",
        exchange_operating_mic: exchange_operating_mic
      )
    end
  end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Check what parse_ticker expects (binance_public.rb:324) and conform the symbol to that format before calling.
  2. Gate calls: only route crypto symbols to BinancePublic (e.g. via exchange MIC == BINANCE_MIC or a crypto asset type), never equities.
  3. Rescue Provider::BinancePublic::Error in lookups so one unsupported ticker does not break a bulk refresh.
  4. If the symbol should be supported, verify the quote currency is one the parser recognizes and fix/extend the mapping.

Example fix

# before
info = provider.fetch_security_info(symbol: "AAPL", exchange_operating_mic: "BINANCE") # raises

# after
crypto_symbol = symbol if mic == "BINANCE"
info = provider.fetch_security_info(symbol: crypto_symbol, exchange_operating_mic: mic) if crypto_symbol.present?
Defensive patterns

Strategy: validation

Validate before calling

CRYPTO_PAIR = /\A[A-Z0-9]{2,10}-(USDT|USDC|FDUSD|USD|BTC|ETH)\z/
return unless mic == "BINANCE" && symbol.match?(CRYPTO_PAIR)

Type guard

def binance_ticker?(symbol, mic)
  mic == "BINANCE" && symbol.match?(%r{\A[A-Z0-9]{2,10}-(USDT|USDC|FDUSD|USD)\z}).present?
end

Try / catch

begin
  info = provider.fetch_security_info(symbol: sym, exchange_operating_mic: mic)
rescue Provider::BinancePublic::Error => e
  Rails.logger.warn("SecurityInfo skipped for #{sym}: #{e.message}")
  nil
end

Prevention

When it happens

Trigger: Passing a non-crypto symbol ("AAPL") or a malformed crypto symbol to fetch_security_info; a quote asset the parser does not map to a Binance pair; a symbol with unexpected separators/casing; calling the securities provider with exchange_operating_mic for a different exchange but a Binance-only code path.

Common situations: Auto-sync iterating a mixed portfolio (stocks + crypto) and routing every symbol to BinancePublic; user-typed symbols that skip normalization; symbol data imported from another provider (e.g. "BTC-USD" style vs the expected format); legacy Security rows with odd symbols.

Related errors


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