phacility/phabricator · critical · Exception
Attempting to apply a charge using an inactive payment…
Error message
Attempting to apply a charge using an inactive payment method ("%s")! What it means
PhortuneCart::willApplyCharge() throws before opening the charge transaction because the supplied PhortunePaymentMethod is not active. Charging a removed or disabled instrument is never valid: the method was likely revoked between selection and charge, and billing against it would be unauthorized. The guard keeps the charge ledger consistent with the method table.
Solutions
- Reload the method immediately before charging using PhortunePaymentMethodQuery with withStatuses(array(PhortunePaymentMethod::STATUS_ACTIVE)); a removed method then simply fails to load and you can prompt for a new one.
- Check $method->isActive() right before willApplyCharge() and surface a payment-method update step instead of charging.
- For subscriptions, keep the default payment method current and act on the billing-problem email Phortune sends when the method is invalid.
Example fix
// before
$method = id(new PhortunePaymentMethodQuery())
->setViewer($viewer)
->withPHIDs(array($method_phid))
->executeOne();
$charge = $cart->willApplyCharge($viewer, $provider, $method); // throws if removed since load
// after
$method = id(new PhortunePaymentMethodQuery())
->setViewer($viewer)
->withPHIDs(array($method_phid))
->withStatuses(array(PhortunePaymentMethod::STATUS_ACTIVE))
->executeOne();
if (!$method) {
throw new Exception(pht('Payment method is no longer available.'));
}
$charge = $cart->willApplyCharge($viewer, $provider, $method); Defensive patterns
Strategy: validation
Validate before calling
$method = id(new PhortunePaymentMethodQuery())
->setViewer($viewer)
->withPHIDs(array($method_phid))
->withStatuses(array(PhortunePaymentMethod::STATUS_ACTIVE))
->executeOne();
if (!$method || !$method->isActive()) {
// ask the user to choose another payment method; do not charge
} Type guard
function isChargeablePaymentMethod(PhortunePaymentMethod $method) {
return $method->isActive();
} Prevention
- Always load payment methods with withStatuses(array(STATUS_ACTIVE)) right before charging.
- Never cache a method object across long-running request steps.
- For subscriptions, react promptly to billing-problem notifications about invalid methods.
When it happens
Trigger: Calling $cart->willApplyCharge($actor, $provider, $method) with $method->isActive() false - typically a stale method object loaded before the user removed/disabled it, or a subscription whose defaultPaymentMethodPHID now points at a non-active method.
Common situations: Automatic subscription billing racing a user deleting their card in another session; checkout flows holding a method object across multiple request steps; payment methods created directly in the database without STATUS_ACTIVE during testing.
Related errors
- All members of the account
- Charge has no transaction ID!
- Charge is in the wrong refunding state!
- Invalid currency format
- Maximum allowed amount is
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/d68a5eeaf452a9d4.
Report an issue: GitHub.
Appendix: source
Thrown at src/applications/phortune/storage/PhortuneCart.php:123
public function willApplyCharge(
PhabricatorUser $actor,
PhortunePaymentProvider $provider,
PhortunePaymentMethod $method = null) {
$account = $this->getAccount();
$charge = PhortuneCharge::initializeNewCharge()
->setAccountPHID($account->getPHID())
->setCartPHID($this->getPHID())
->setAuthorPHID($actor->getPHID())
->setMerchantPHID($this->getMerchant()->getPHID())
->setProviderPHID($provider->getProviderConfig()->getPHID())
->setAmountAsCurrency($this->getTotalPriceAsCurrency());
if ($method) {
if (!$method->isActive()) {
throw new Exception(
pht(
'Attempting to apply a charge using an inactive '.
'payment method ("%s")!',
$method->getPHID()));
}
$charge->setPaymentMethodPHID($method->getPHID());
}
$this->openTransaction();
$this->beginReadLocking();
$copy = clone $this;
$copy->reload();
if ($copy->getStatus() !== self::STATUS_READY) {
throw new Exception(
pht(
'Cart has wrong status ("%s") to call %s, expected "%s".',View on GitHub (pinned to 5720a38cfe)