{"record":{"id":"937a1399c1fc21a2","repo":"phacility/phabricator","slug":"this-order-can-not-be-cancelled-because-the-applic","errorCode":null,"errorMessage":"This order can not be cancelled because the application has not finished building it yet.","messagePattern":"This order can not be cancelled because the application has not finished building it yet\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"src/applications/phortune/storage/PhortuneCart.php","lineNumber":514,"sourceCode":"      return true;\n    } catch (Exception $ex) {\n      return false;\n    }\n  }\n\n  public function canVoidOrder() {\n    try {\n      $this->assertCanVoidOrder();\n      return true;\n    } catch (Exception $ex) {\n      return false;\n    }\n  }\n\n  public function assertCanCancelOrder() {\n    switch ($this->getStatus()) {\n      case self::STATUS_BUILDING:\n        throw new Exception(\n          pht(\n            'This order can not be cancelled because the application has not '.\n            'finished building it yet.'));\n      case self::STATUS_READY:\n        throw new Exception(\n          pht(\n            'This order can not be cancelled because it has not been placed.'));\n    }\n\n    return $this->getImplementation()->assertCanCancelOrder($this);\n  }\n\n  public function assertCanRefundOrder() {\n    switch ($this->getStatus()) {\n      case self::STATUS_BUILDING:\n        throw new Exception(\n          pht(\n            'This order can not be refunded because the application has not '.","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/phortune/storage/PhortuneCart.php#L496-L532","documentation":"PhortuneCart::assertCanCancelOrder() throws when the cart is still STATUS_BUILDING: the owning application has not finished adding purchases, so cancelling now would tear down a half-built order. The companion canCancelOrder() catches this and returns false. It is an expected user-facing state check, not corruption.","triggerScenarios":"Calling assertCanCancelOrder() (or a cancel controller built on it) on a cart whose status is still PhortuneCart::STATUS_BUILDING - typically right after cart creation, before the application has activated it for checkout.","commonSituations":"Users clicking cancel during the brief building phase of an application-driven order; custom checkout UIs offering cancel too early; orphaned carts left in BUILDING by an application error.","solutions":["Gate the cancel action on $cart->canCancelOrder() and show a 'not ready yet' state when it returns false.","Let the owning application finish building and activating the cart before offering cancellation.","If carts are stuck in BUILDING, investigate why the application never completed them rather than force-cancelling."],"exampleFix":"// before\n$cart->assertCanCancelOrder(); // throws while the cart is still being built\n\n// after\nif (!$cart->canCancelOrder()) {\n  return $this->newDialog()\n    ->setTitle(pht('Unable to Cancel Order'))\n    ->appendParagraph(pht('This order can not be cancelled yet.'));\n}\n// proceed with cancellation","handlingStrategy":"validation","validationCode":"if (!$cart->canCancelOrder()) {\n  // cart still building or not placed; do not offer cancellation\n  return $this->newDialog()->setTitle(pht('Unable to Cancel Order'));\n}","typeGuard":"function isCancellableCart(PhortuneCart $cart) {\n  return $cart->canCancelOrder();\n}","tryCatchPattern":"try {\n  $cart->assertCanCancelOrder();\n} catch (Exception $ex) {\n  // show $ex->getMessage() to the user; statuses BUILDING/READY are expected states\n}","preventionTips":["Gate cancel UI on canCancelOrder() instead of calling assertCanCancelOrder() unconditionally.","Only offer cancellation after the owning application activates the cart.","Investigate carts stuck in BUILDING instead of forcing cancellation."],"tags":["phortune","phabricator","php","payments","cart","order-lifecycle"],"backgroundTag":"invalid-cart-status","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}