{"record":{"id":"8a0fd295bf761da3","repo":"phacility/phabricator","slug":"minimum-allowed-amount-is-s","errorCode":null,"errorMessage":"Minimum allowed amount is %s.","messagePattern":"Minimum allowed amount is (.+?)\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/phortune/currency/PhortuneCurrency.php","lineNumber":218,"sourceCode":"   * @return this\n   */\n  public function assertInRange($minimum, $maximum) {\n    if ($minimum !== null && $maximum !== null) {\n      $min = self::newFromString($minimum);\n      $max = self::newFromString($maximum);\n      if ($min->value > $max->value) {\n        throw new Exception(\n          pht(\n            'Range (%s - %s) is not valid!',\n            $min->formatForDisplay(),\n            $max->formatForDisplay()));\n      }\n    }\n\n    if ($minimum !== null) {\n      $min = self::newFromString($minimum);\n      if ($min->value > $this->value) {\n        throw new Exception(\n          pht(\n            'Minimum allowed amount is %s.',\n            $min->formatForDisplay()));\n      }\n    }\n\n    if ($maximum !== null) {\n      $max = self::newFromString($maximum);\n      if ($max->value < $this->value) {\n        throw new Exception(\n          pht(\n            'Maximum allowed amount is %s.',\n            $max->formatForDisplay()));\n      }\n    }\n\n    return $this;\n  }","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/phortune/currency/PhortuneCurrency.php#L200-L236","documentation":"Thrown by PhortuneCurrency::assertInRange($minimum, $maximum) when the object's value (stored internally as integer cents) is strictly below the parsed $minimum. assertInRange is Phortune's bounds-check API: both bounds are currency strings parsed with newFromString(), null skips a check, and the bounds are inclusive. The message reports the minimum formatted for display (e.g. '$5.00 USD') so the caller can surface it directly to a user.","triggerScenarios":"Calling e.g. PhortuneCurrency::newFromString('1.00 USD')->assertInRange('5.00 USD', null) — 100 cents < 500 cents throws. Also assertInRange('5.00 USD', '10.00 USD') on a $1.00 product price, or a range check on a cart total that falls under a provider's minimum charge.","commonSituations":"Product/subscription pricing forms with a minimum purchase floor; enforcing a payment gateway's minimum transaction size; validating a refund or credit amount that legitimately went negative while the minimum assumed non-negative; unit fixtures that forget the bound strings are decimal dollars while stored values are cents.","solutions":["Raise the value being validated so it meets the minimum shown in the message.","Re-check that the minimum string itself is what you intended — a '5' meaning 5 cents vs '$5.00' meaning 500 cents mixup is the most common cause.","If negative amounts (account credit/debt) are legitimate, pass null as the minimum or use a negative bound; assertInRange exists precisely because zero-checks alone are wrong for signed balances.","Wrap the call in try/catch Exception and convert the message into a form-field validation error instead of a 500."],"exampleFix":"// before\n$price->assertInRange('5.00 USD', '500.00 USD');\n\n// after\ntry {\n  $price->assertInRange('5.00 USD', '500.00 USD');\n} catch (Exception $ex) {\n  $e = new PhabricatorApplicationTransactionValidationError(\n    PhortuneProductTransaction::TRANSACTIONTYPE,\n    pht('Invalid'),\n    $ex->getMessage(),\n    null);\n  throw new PhabricatorApplicationTransactionValidationException(array($e));\n}","handlingStrategy":"validation","validationCode":"// Compare in cents BEFORE calling assertInRange.\nfunction currency_meets_minimum(PhortuneCurrency $amount, $minimum_string) {\n  if ($minimum_string === null) {\n    return true;\n  }\n  $min = PhortuneCurrency::newFromString($minimum_string);\n  return $amount->getValue() >= $min->getValue();\n}\n\nif (!currency_meets_minimum($price, $minimum)) {\n  $field_error = pht(\n    'Minimum allowed amount is %s.',\n    PhortuneCurrency::newFromString($minimum)->formatForDisplay());\n}","typeGuard":null,"tryCatchPattern":"try {\n  $price->assertInRange($minimum, $maximum);\n} catch (Exception $ex) {\n  // Message already carries the violated bound, e.g. 'Minimum allowed amount is $5.00 USD.'\n  throw new PhabricatorApplicationTransactionValidationException(\n    array(\n      new PhabricatorApplicationTransactionValidationError(\n        $transaction_type,\n        pht('Invalid'),\n        $ex->getMessage(),\n        null),\n    ));\n}","preventionTips":["Remember the unit split: strings are decimal dollars, getValue() is integer cents — convert before comparing.","Validate the bound strings themselves with newFromString() once, at config load, so bad bounds fail loudly at deploy time.","For balances that may legitimately be negative, pass null as the lower bound instead of '0.00 USD'."],"tags":["php","phabricator","phortune","currency","range-validation","payments"],"backgroundTag":"value-out-of-range","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}