phacility/phabricator · warning · Exception

This order can not be cancelled because it has not been plac

Error message

This order can not be cancelled because it has not been placed.

What it means

assertCanCancelOrder() throws when the cart is STATUS_READY: the order has been built but the user never completed checkout, so it has not been placed yet. Nothing has been charged, so there is no order to cancel - Phortune expects READY carts to simply expire or be checked out. Use canCancelOrder() to test without throwing.

Source

Thrown at src/applications/phortune/storage/PhortuneCart.php:519

  public function canVoidOrder() {
    try {
      $this->assertCanVoidOrder();
      return true;
    } catch (Exception $ex) {
      return false;
    }
  }

  public function assertCanCancelOrder() {
    switch ($this->getStatus()) {
      case self::STATUS_BUILDING:
        throw new Exception(
          pht(
            'This order can not be cancelled because the application has not '.
            'finished building it yet.'));
      case self::STATUS_READY:
        throw new Exception(
          pht(
            'This order can not be cancelled because it has not been placed.'));
    }

    return $this->getImplementation()->assertCanCancelOrder($this);
  }

  public function assertCanRefundOrder() {
    switch ($this->getStatus()) {
      case self::STATUS_BUILDING:
        throw new Exception(
          pht(
            'This order can not be refunded because the application has not '.
            'finished building it yet.'));
      case self::STATUS_READY:
        throw new Exception(
          pht(
            'This order can not be refunded because it has not been placed.'));

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Check $cart->canCancelOrder() first and hide the cancel action for unplaced orders.
  2. For READY carts, simply abandon them - no cancellation is required since nothing was purchased.
  3. In bulk tooling, skip carts whose status is READY or BUILDING.
Defensive patterns

Strategy: validation

Validate before calling

if ($cart->getStatus() === PhortuneCart::STATUS_READY) {
  // unplaced order: nothing to cancel; let it expire or complete checkout
}
if (!$cart->canCancelOrder()) {
  return $this->newDialog()->setTitle(pht('Unable to Cancel Order'));
}

Type guard

function isPlacedCart(PhortuneCart $cart) {
  return !in_array(
    $cart->getStatus(),
    array(PhortuneCart::STATUS_BUILDING, PhortuneCart::STATUS_READY));
}

Prevention

When it happens

Trigger: Calling assertCanCancelOrder() on a cart in PhortuneCart::STATUS_READY, e.g. a user opening an old unpaid checkout link and choosing cancel.

Common situations: Abandoned checkouts being cleaned up manually; links to ready carts resurfacing in email; scripts iterating all carts and calling cancel unconditionally.

Related errors


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