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
- Re-enable (or re-create) the provider configuration in Phortune admin so its charges can be refunded through it
- If the provider is permanently gone, refund directly at the gateway and record manual refunds, or migrate the charges to a replacement provider config
- 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
- Keep provider configs installed until every charge through them is refunded/settled
- Validate the provider map covers all charges before running cancel/refund flows
- When retiring a provider, migrate or manually settle its charges first
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
- Unable to refund some charges!
- Unable to load provider for charge!
- There are no payment providers enabled that can add payment
- Charge has no transaction ID!
- Unable to refund charge; no Stripe chargeID!
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/058972581b6fc132.
Report an issue: GitHub.