we-promise/sure · warning

Invalid currency code '#{currency_value}' for <%= class_name

Error message

Invalid currency code '#{currency_value}' for <%= class_name %> account #{id}, defaulting to USD

What it means

Global (e.g. crypto) provider generator template. The generated account model includes CurrencyNormalizable and upsert_<provider>_snapshot! assigns currency: parse_currency(snapshot[:currency]) || "USD". parse_currency requires a 3-letter uppercase code recognized by the Money gem; when the snapshot's currency fails that check, the model's log_invalid_currency override emits this warning and the account silently persists with USD.

Source

Thrown at lib/generators/provider/global/templates/global_account_model.rb.tt:50

        name: snapshot[:institution_name],
        logo: snapshot[:institution_logo]
      }.compact,
      raw_payload: account_snapshot
    )
  end

  def upsert_<%= file_name %>_transactions_snapshot!(transactions_snapshot)
    assign_attributes(
      raw_transactions_payload: transactions_snapshot
    )

    save!
  end

  private

  def log_invalid_currency(currency_value)
    Rails.logger.warn("Invalid currency code '#{currency_value}' for <%= class_name %> account #{id}, defaulting to USD")
  end
end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Check the account's raw_payload for the exact currency/symbol string the provider sent
  2. Add a symbol-to-ISO mapping in the generated upsert (e.g. "USDT" -> "USD", "WBTC" -> "BTC") before parse_currency, and mirror it in lib/generators/provider/global/templates/global_account_model.rb.tt
  3. For token-denominated balances that have no ISO code, decide an explicit conversion policy instead of relying on the silent USD default
  4. If snapshot[:currency] is nil, require the provider field or default intentionally rather than via the Money-gem miss

Example fix

# generated global account model - before
currency: parse_currency(snapshot[:currency]) || "USD",

# after
TOKEN_TO_ISO = { "USDT" => "USD", "USDC" => "USD", "WBTC" => "BTC" }.freeze

currency: parse_currency(TOKEN_TO_ISO.fetch(snapshot[:currency].to_s.strip.upcase, snapshot[:currency])) || "USD",
Defensive patterns

Strategy: validation

Validate before calling

# Validate/translate crypto symbols before persisting the snapshot
TOKEN_TO_ISO = { "USDT" => "USD", "USDC" => "USD", "WBTC" => "BTC" }.freeze

raw = snapshot[:currency].to_s.strip.upcase
candidate = TOKEN_TO_ISO.fetch(raw, raw)
begin
  currency = Money::Currency.new(candidate).iso_code
rescue Money::Currency::UnknownCurrencyError
  currency = "USD" # or raise/report for token-denominated balances
end

Type guard

def tradable_currency?(value)
  return false if value.blank?

  Money::Currency.new(value.to_s.strip.upcase)
  true
rescue Money::Currency::UnknownCurrencyError
  false
end

Prevention

When it happens

Trigger: Crypto/global providers returning non-ISO asset symbols that the Money gem does not know: "USDT", "WBTC", "1INCH" (starts with a digit, fails \A[A-Z]{3}\z), symbols with hyphens, or nil currency fields — failing either the 3-letter regex or Money::Currency.new in app/models/concerns/currency_normalizable.rb.

Common situations: Wallet/exchange APIs whose balances are denominated in tokens rather than fiat codes; stablecoin or wrapped-asset symbols treated as invalid; new listings the Money gem has never heard of — for these the USD fallback produces wrong valuations, so mapping matters more than in the family template.

Related errors


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