{"record":{"id":"d291a1be0c30dfa5","repo":"phacility/phabricator","slug":"unsupported-currency-s","errorCode":null,"errorMessage":"Unsupported currency '%s'!","messagePattern":"Unsupported currency '(.+?)'!","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/phortune/currency/PhortuneCurrency.php","lineNumber":55,"sourceCode":"\n    if (substr_count($value, '-') > 1) {\n      self::throwFormatException($string);\n    }\n\n    if (substr_count($value, '$') > 1) {\n      self::throwFormatException($string);\n    }\n\n    $value = str_replace('$', '', $value);\n    $value = (float)$value;\n    $value = (int)round(100 * $value);\n\n    $currency = idx($matches, 2, $default);\n    switch ($currency) {\n      case 'USD':\n        break;\n      default:\n        throw new Exception(pht(\"Unsupported currency '%s'!\", $currency));\n    }\n\n    return self::newFromValueAndCurrency($value, $currency);\n  }\n\n  public static function newFromValueAndCurrency($value, $currency) {\n    $obj = new PhortuneCurrency();\n\n    $obj->value = $value;\n    $obj->currency = $currency;\n\n    return $obj;\n  }\n\n  public static function newFromList(array $list) {\n    assert_instances_of($list, __CLASS__);\n\n    if (!$list) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/phortune/currency/PhortuneCurrency.php#L37-L73","documentation":"PhortuneCurrency::newFromString parses amount strings like '19.99 USD'; the currency segment (explicit or defaulted) must be exactly USD - the only currency Phortune supports. Any other captured code ('5.00 EUR', '10 GBP') throws Exception \"Unsupported currency '%s'!\". Phortune is deliberately single-currency per install, so no exchange or multi-currency path exists.","triggerScenarios":"Passing '5.00 EUR', '10 GBP', or any non-USD code to PhortuneCurrency::newFromString; custom product code emitting localized currency strings; integrations formatting prices with the buyer's locale currency.","commonSituations":"Non-US developers testing with local currency strings; billing integrations reused from multi-currency systems; copy-pasted price strings including currency symbols or codes.","solutions":["Use USD amounts: '19.99 USD' or a bare '19.99' (USD is the default)","Convert foreign-currency prices to USD before feeding them into Phortune","Do not extend the switch for other currencies unless you fully understand the single-currency assumption baked into Phortune"],"exampleFix":"// before\n$price = PhortuneCurrency::newFromString('5.00 EUR');\n// after\n$price = PhortuneCurrency::newFromString('5.00 USD');","handlingStrategy":"validation","validationCode":"// Normalize to USD before parsing\n$value = strtoupper(trim($value));\nif (preg_match('/(USD)$/', $value) !== 1) {\n  $value = $value.' USD'; // or convert from the source currency first\n}\n$currency = PhortuneCurrency::newFromString($value);","typeGuard":"function isSupportedPhortuneCurrency($currency) {\n  return is_string($currency) && strcasecmp($currency, 'USD') === 0;\n}","tryCatchPattern":null,"preventionTips":["Emit and store Phortune prices as plain USD strings like '19.99 USD'","Validate currency codes against USD before calling newFromString","Convert foreign-currency amounts upstream - Phortune has no multi-currency support"],"tags":["phabricator","phortune","currency","payments","parsing"],"backgroundTag":"unsupported-currency","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}