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
This is a generator template (rails g provider ...) that emits a provider account model including the CurrencyNormalizable concern. During upsert_from_<provider>!, extract_currency calls parse_currency, which upcases/strips the provider value and requires both a strict 3-letter format (\A[A-Z]{3}\z) and recognition by the Money gem (Money::Currency.new). On failure, log_invalid_currency (the model's override that adds account context) warns and parse_currency returns nil, so the caller falls back to "USD" via extract_currency(data, fallback: "USD").
Source
Thrown at lib/generators/provider/family/templates/account_model.rb.tt:123
<% if investment_provider? -%>
return unless <%= file_name %>_authorization_id.present?
<%= class_name %>ConnectionCleanupJob.perform_later(
<%= file_name %>_item_id: <%= file_name %>_item.id,
authorization_id: <%= file_name %>_authorization_id,
account_id: id
)
<% else -%>
<%= class_name %>ConnectionCleanupJob.perform_later(
<%= file_name %>_item_id: <%= file_name %>_item.id,
account_id: id
)
<% end -%>
end
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
- Inspect the saved raw_payload for the account id in the log to see the exact currency value the provider sent
- If the code is a known provider convention, add a translation map in extract_currency (e.g. "GBX" => "GBP", "USDT" => "USD") before calling parse_currency, in both the generated model and the .tt template so regeneration keeps it
- If the provider genuinely omits currency for some account types, keep the USD fallback and accept the warning
- Feed back real-world codes into lib/generators/provider/family/templates/account_model.rb.tt so future generated providers map them
Example fix
# generated model - before
currency: extract_currency(data, fallback: "USD"),
# generated model - after (add mapping helper)
currency: extract_currency(data, fallback: "USD"),
# and inside the generated/private section:
def extract_currency(data, fallback:)
raw = data[:currency].to_s.strip.upcase
raw = { "GBX" => "GBP", "USDT" => "USD", "GBp" => "GBP" }.fetch(raw, raw)
parse_currency(raw) || fallback
end Defensive patterns
Strategy: validation
Validate before calling
# Pre-validate provider currency before upsert (generated model or processor)
KNOWN = { "GBX" => "GBP", "GBp" => "GBP", "USDT" => "USD" }
raw = data[:currency].to_s.strip.upcase
normalized = Money::Currency.new(KNOWN.fetch(raw, raw)) rescue nil
currency = normalized&.iso_code || "USD" Type guard
# Ruby guard: true when the provider value maps to a real Money currency
def valid_provider_currency?(value)
return false if value.blank?
normalized = value.to_s.strip.upcase
return false unless normalized.match?(/\A[A-Z]{3}\z/)
Money::Currency.new(normalized)
true
rescue Money::Currency::UnknownCurrencyError
false
end Prevention
- When generating a new provider, collect the provider's real currency enum from its API docs and encode it in extract_currency on day one
- Monitor this warning per provider and treat new values as provider-API-change signals, not noise
- Prefer storing raw payload alongside so mis-mapped currencies can be repaired retroactively
When it happens
Trigger: Provider account payload whose currency field is not a valid ISO-4217 code recognized by the Money gem: "XXX" (3 letters but unknown to Money), nil/empty, symbols like "$", 4+ letter codes, or non-3-letter strings such as "pence" — anything failing app/models/concerns/currency_normalizable.rb:38 or :45.
Common situations: Brokerage aggregators returning non-ISO codes (GBX pence, USDT crypto codes), sandbox/test fixtures with placeholder currencies, providers sending display strings or localized currency names, provider API changes to the currency field format.
Related errors
- Invalid currency code '#{currency_value}' for <%= class_name
- Could not determine currency for #{symbol} from Tiingo searc
- <%= class_name %>Account::ActivitiesProcessor - Unmapped act
- Invalid institution URL for <%= class_name %> account #{prov
- Unexpected response format from search endpoint
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/9221342dc6131e30.
Report an issue: GitHub.