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

  1. Validate $amount->isPositive() before calling and reject zero-value submissions in the form with a field error.
  2. Build amounts with PhortuneCurrency::newFromUserInput()/newFromString() and re-validate after parsing.
  3. 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

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


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/23b0583fd6013e7d. Report an issue: GitHub.