phacility/phabricator · error · Exception

Unable to load provider for charge!

Error message

Unable to load provider for charge!

What it means

PhortuneCartUpdateController refreshes each non-refund charge by looking up its providerPHID in the provider-config map and calling updateCharge(). When the charge's provider configuration no longer exists or is not among the loaded providers, idx() yields null and the controller throws 'Unable to load provider for charge!'. The charge originated from a provider that has since been removed or disabled.

Source

Thrown at src/applications/phortune/controller/cart/PhortuneCartUpdateController.php:50

    if ($charges) {
      $providers = id(new PhortunePaymentProviderConfigQuery())
        ->setViewer($viewer)
        ->withPHIDs(mpull($charges, 'getProviderPHID'))
        ->execute();
      $providers = mpull($providers, null, 'getPHID');
    } else {
      $providers = array();
    }

    foreach ($charges as $charge) {
      if ($charge->isRefund()) {
        // Don't update refunds.
        continue;
      }

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

      $provider = $provider_config->buildProvider();
      $provider->updateCharge($charge);
    }

    return id(new AphrontRedirectResponse())
      ->setURI($cart->getDetailURI());
  }

}

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Re-enable or re-create the missing provider configuration so its charges can be updated and refunded
  2. If retiring a provider, first settle or migrate all charges that reference it
  3. As a last resort, record gateway-side state manually and neutralize the orphaned charges
Defensive patterns

Strategy: validation

Validate before calling

// Confirm each charge maps to a live provider before updating
foreach ($charges as $charge) {
  if (!$charge->isRefund() && idx($providers, $charge->getProviderPHID()) === null) {
    continue; // or flag the cart for manual reconciliation
  }
}

Prevention

When it happens

Trigger: Clicking 'Update Charges' (or hitting the update endpoint) on a cart whose provider config was deleted or disabled after checkout; provider restricted away from the merchant; mixed-provider carts where one provider was retired.

Common situations: Providers removed after migrating payment processors; test providers disabled in production leaving old carts; provider configs cleaned up during deprovisioning.

Related errors


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