phacility/phabricator · warning · Exception
This order can not be voided because it is not ready for pay
Error message
This order can not be voided because it is not ready for payment.
What it means
assertCanVoidOrder() throws when an invoice cart's status is anything other than STATUS_READY: an invoice may only be voided while it is still awaiting payment. Once it has been paid (or is otherwise in flight), the correct remedy is a refund, not a void. The READY-only rule keeps the invoice lifecycle consistent.
Source
Thrown at src/applications/phortune/storage/PhortuneCart.php:554
pht(
'This order can not be refunded because it has not been placed.'));
}
return $this->getImplementation()->assertCanRefundOrder($this);
}
public function assertCanVoidOrder() {
if (!$this->getIsInvoice()) {
throw new Exception(
pht(
'This order can not be voided because it is not an invoice.'));
}
switch ($this->getStatus()) {
case self::STATUS_READY:
break;
default:
throw new Exception(
pht(
'This order can not be voided because it is not ready for '.
'payment.'));
}
return null;
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'metadata' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'status' => 'text32',
'cartClass' => 'text128',View on GitHub (pinned to 5720a38cfe)
Solutions
- Check status (or wrap in canVoidOrder-style logic) and only offer void while the invoice awaits payment.
- If the invoice was already paid, use the refund flow instead of void.
- When auto-billing is enabled for a subscription, pause billing before voiding to avoid the charge/void race.
Defensive patterns
Strategy: validation
Validate before calling
if ($cart->getIsInvoice() &&
$cart->getStatus() !== PhortuneCart::STATUS_READY) {
// invoice no longer awaiting payment: use refund instead of void
} Type guard
function isVoidableInvoiceCart(PhortuneCart $cart) {
return (bool)$cart->getIsInvoice()
&& $cart->getStatus() === PhortuneCart::STATUS_READY;
} Try / catch
try {
$cart->assertCanVoidOrder();
} catch (Exception $ex) {
// show $ex->getMessage(); if already paid, route the user to refund instead
} Prevention
- Only allow void while the invoice status is STATUS_READY.
- Pause subscription auto-billing before voiding to avoid the charge/void race.
- Route already-paid invoices to the refund flow.
When it happens
Trigger: Calling assertCanVoidOrder() on an invoice cart whose status is not PhortuneCart::STATUS_READY - for example one that was already charged or is processing.
Common situations: Attempting to void an invoice after the subscription already auto-charged it; race between the billing worker charging the invoice and a manager voiding it; retrying a void on an already-voided or processed invoice.
Related errors
- This order can not be voided because it is not an invoice.
- This order can not be cancelled because the application has
- This order can not be cancelled because it has not been plac
- This order can not be refunded because the application has n
- This order can not be refunded because it has not been place
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/4467e6647335105f.
Report an issue: GitHub.