{"record":{"id":"9221342dc6131e30","repo":"we-promise/sure","slug":"invalid-currency-code-currency-value-for","errorCode":null,"errorMessage":"Invalid currency code '#{currency_value}' for <%= class_name %> account #{id}, defaulting to USD","messagePattern":"Invalid currency code '#(.+?)' for <%= class_name %> account #(.+?), defaulting to USD","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"lib/generators/provider/family/templates/account_model.rb.tt","lineNumber":123,"sourceCode":"\n<% if investment_provider? -%>\n      return unless <%= file_name %>_authorization_id.present?\n\n      <%= class_name %>ConnectionCleanupJob.perform_later(\n        <%= file_name %>_item_id: <%= file_name %>_item.id,\n        authorization_id: <%= file_name %>_authorization_id,\n        account_id: id\n      )\n<% else -%>\n      <%= class_name %>ConnectionCleanupJob.perform_later(\n        <%= file_name %>_item_id: <%= file_name %>_item.id,\n        account_id: id\n      )\n<% end -%>\n    end\n\n    def log_invalid_currency(currency_value)\n      Rails.logger.warn(\"Invalid currency code '#{currency_value}' for <%= class_name %> account #{id}, defaulting to USD\")\n    end\nend\n","sourceCodeStart":105,"sourceCodeEnd":126,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/lib/generators/provider/family/templates/account_model.rb.tt#L105-L126","documentation":"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\").","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# generated model - before\ncurrency: extract_currency(data, fallback: \"USD\"),\n\n# generated model - after (add mapping helper)\ncurrency: extract_currency(data, fallback: \"USD\"),\n\n# and inside the generated/private section:\ndef extract_currency(data, fallback:)\n  raw = data[:currency].to_s.strip.upcase\n  raw = { \"GBX\" => \"GBP\", \"USDT\" => \"USD\", \"GBp\" => \"GBP\" }.fetch(raw, raw)\n  parse_currency(raw) || fallback\nend","handlingStrategy":"validation","validationCode":"# Pre-validate provider currency before upsert (generated model or processor)\nKNOWN = { \"GBX\" => \"GBP\", \"GBp\" => \"GBP\", \"USDT\" => \"USD\" }\nraw = data[:currency].to_s.strip.upcase\nnormalized = Money::Currency.new(KNOWN.fetch(raw, raw)) rescue nil\ncurrency = normalized&.iso_code || \"USD\"","typeGuard":"# Ruby guard: true when the provider value maps to a real Money currency\ndef valid_provider_currency?(value)\n  return false if value.blank?\n  normalized = value.to_s.strip.upcase\n  return false unless normalized.match?(/\\A[A-Z]{3}\\z/)\n\n  Money::Currency.new(normalized)\n  true\nrescue Money::Currency::UnknownCurrencyError\n  false\nend","tryCatchPattern":null,"preventionTips":["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"],"tags":["currency","money-gem","provider-data","generator-template","fallback"],"backgroundTag":"invalid-currency-code","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}