phacility/phabricator · error · Exception

Unable to load provider for charge!

Error message

Unable to load provider for charge!

What it means

While cancelling a cart that carries charges, Phortune refunds each charge by looking up charge->getProviderPHID() in the loaded provider-config map. If the charge was created through a provider whose configuration has since been deleted, disabled, or is unavailable to that merchant, idx() returns null and the controller throws 'Unable to load provider for charge!'. The refund cannot be routed without the provider implementation.

Source

Thrown at src/applications/phortune/controller/cart/PhortuneCartCancelController.php:121

          $providers = array();
        }

        foreach ($charges as $charge) {
          $refundable = $charge->getAmountRefundableAsCurrency();
          if (!$refundable->isPositive()) {
            // This charge is a refund, or has already been fully refunded.
            continue;
          }

          if ($refund->isGreaterThan($refundable)) {
            $refund_amount = $refundable;
          } else {
            $refund_amount = $refund;
          }

          $provider_config = idx($providers, $charge->getProviderPHID());
          if (!$provider_config) {
            throw new Exception(pht('Unable to load provider for charge!'));
          }

          $provider = $provider_config->buildProvider();

          $refund_charge = $cart->willRefundCharge(
            $viewer,
            $provider,
            $charge,
            $refund_amount);

          $refunded = false;
          try {
            $provider->refundCharge($charge, $refund_charge);
            $refunded = true;
          } catch (Exception $ex) {
            phlog($ex);
            $cart->didFailRefund($charge, $refund_charge);
          }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Re-enable (or re-create) the provider configuration in Phortune admin so its charges can be refunded through it
  2. If the provider is permanently gone, refund directly at the gateway and record manual refunds, or migrate the charges to a replacement provider config
  3. Keep old provider configs installed-but-restricted until every charge through them is settled
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every charge's provider is resolvable before starting refunds
foreach ($charges as $charge) {
  if (!$charge->isRefund() && empty($providers[$charge->getProviderPHID()])) {
    throw new Exception(
      pht('Charge %s has no available provider; re-enable its provider config.',
        $charge->getID()));
  }
}

Prevention

When it happens

Trigger: Refunding/cancelling a cart whose payment provider config was deleted after the charge was made; provider disabled during incident cleanup; provider moved to another merchant leaving old charges orphaned.

Common situations: Ops removes a test provider after going live while old test carts remain; provider migrations that drop configs; long-lived HOLD carts from before a provider swap.

Related errors


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