phacility/phabricator · error · Exception
Trying to refund non-positive amount of money!
Error message
Trying to refund non-positive amount of money!
What it means
PhortuneCart::willRefundCharge() validates the refund amount first and throws when the PhortuneCurrency passed is zero or negative. Refund amounts must be strictly positive because the refund charge record is stored with the amount negated. A non-positive value therefore means the caller computed or parsed the amount incorrectly.
Source
Thrown at src/applications/phortune/storage/PhortuneCart.php:315
// Move the cart back into STATUS_READY so the user can try
// making the purchase again.
$this->setStatus(self::STATUS_READY)->save();
$this->endReadLocking();
$this->saveTransaction();
return $this;
}
public function willRefundCharge(
PhabricatorUser $actor,
PhortunePaymentProvider $provider,
PhortuneCharge $charge,
PhortuneCurrency $amount) {
if (!$amount->isPositive()) {
throw new Exception(
pht('Trying to refund non-positive amount of money!'));
}
if ($amount->isGreaterThan($charge->getAmountRefundableAsCurrency())) {
throw new Exception(
pht('Trying to refund more money than remaining on charge!'));
}
if ($charge->getRefundedChargePHID()) {
throw new Exception(
pht('Trying to refund a refund!'));
}
if (($charge->getStatus() !== PhortuneCharge::STATUS_CHARGED) &&
($charge->getStatus() !== PhortuneCharge::STATUS_HOLD)) {
throw new Exception(
pht('Trying to refund an uncharged charge!'));
}View on GitHub (pinned to 5720a38cfe)
Solutions
- Validate $amount->isPositive() before calling and reject zero-value submissions in the form with a field error.
- Build amounts with PhortuneCurrency::newFromUserInput()/newFromString() and re-validate after parsing.
- Skip the refund entirely when a computed amount rounds down to zero.
Example fix
// before
$amount = PhortuneCurrency::newFromUserInput($request->getStr('amount'));
$refund = $cart->willRefundCharge($actor, $provider, $charge, $amount); // throws on '0.00' or negative
// after
$amount = PhortuneCurrency::newFromUserInput($request->getStr('amount'));
if (!$amount->isPositive()) {
$errors[] = pht('Refund amount must be greater than zero.');
} else {
$refund = $cart->willRefundCharge($actor, $provider, $charge, $amount);
} Defensive patterns
Strategy: validation
Validate before calling
$amount = PhortuneCurrency::newFromUserInput($raw);
if (!$amount->isPositive()) {
$errors[] = pht('Refund amount must be greater than zero.');
}
// only call willRefundCharge() when $errors is empty Try / catch
try {
$cart->willRefundCharge($actor, $provider, $charge, $amount);
} catch (Exception $ex) {
// surface $ex->getMessage() as a form error; non-positive amounts are caller bugs
} Prevention
- Validate amounts with isPositive() before every refund call.
- Parse refund input with PhortuneCurrency helpers rather than manual arithmetic.
- Skip zero-value refunds instead of passing them through.
When it happens
Trigger: Calling willRefundCharge() with an amount parsed from empty input (e.g. PhortuneCurrency::newFromString('0.00')), a negative value produced by sign arithmetic, or a currency whose value was never set.
Common situations: Refund forms submitted with a blank amount; proration math that yields zero for the final period; reusing a negated refund currency as input to a second refund.
Related errors
- Invalid currency format ('%s').
- Charge has no transaction ID!
- Unable to refund charge; no Stripe chargeID!
- Trying to refund more money than remaining on charge!
- Trying to refund a refund!
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/23b0583fd6013e7d.
Report an issue: GitHub.