{"record":{"id":"ce1e676db87b6c7e","repo":"phacility/phabricator","slug":"failed-to-load-subscription-with-phid-s","errorCode":null,"errorMessage":"Failed to load subscription with PHID \"%s\".","messagePattern":"Failed to load subscription with PHID \"(.+?)\"\\.","errorType":"exception","errorClass":"PhabricatorWorkerPermanentFailureException","httpStatus":null,"severity":"error","filePath":"src/applications/phortune/worker/PhortuneSubscriptionWorker.php","lineNumber":213,"sourceCode":"\n\n  /**\n   * Load the subscription to generate an invoice for.\n   *\n   * @return PhortuneSubscription The subscription to invoice.\n   */\n  private function loadSubscription() {\n    $viewer = PhabricatorUser::getOmnipotentUser();\n\n    $data = $this->getTaskData();\n    $subscription_phid = idx($data, 'subscriptionPHID');\n\n    $subscription = id(new PhortuneSubscriptionQuery())\n      ->setViewer($viewer)\n      ->withPHIDs(array($subscription_phid))\n      ->executeOne();\n    if (!$subscription) {\n      throw new PhabricatorWorkerPermanentFailureException(\n        pht(\n          'Failed to load subscription with PHID \"%s\".',\n          $subscription_phid));\n    }\n\n    return $subscription;\n  }\n\n\n  /**\n   * Get the start and end epoch timestamps for this billing period.\n   *\n   * @param PhortuneSubscription The subscription being billed.\n   * @return pair<int, int> Beginning and end of the billing range.\n   */\n  private function getBillingPeriodRange(PhortuneSubscription $subscription) {\n    $data = $this->getTaskData();\n","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/phortune/worker/PhortuneSubscriptionWorker.php#L195-L231","documentation":"The queued billing task carries subscriptionPHID in its task data, and loadSubscription() re-loads it with an omnipotent-user PhortuneSubscriptionQuery. If the row is gone (almost always because the subscription was deleted), the query returns null and the worker throws a permanent failure. Retrying cannot resurrect a deleted subscription, so the queue discards the task.","triggerScenarios":"A subscription's periodic trigger task fires after the PhortuneSubscription row was deleted; or the task data was hand-edited or re-queued with a PHID that does not exist in the database.","commonSituations":"User deletes a subscription while its trigger task is already in the queue; restoring a database dump while keeping the old worker queue; scripts enqueueing worker tasks with stale or hand-copied PHIDs.","solutions":["Check the phortune_subscription table for the PHID shown in the failed task's data to confirm the subscription is really gone","If the deletion was intentional, no action is needed: let the task record its permanent failure and move on","If triggers keep firing, find and remove the orphaned row in the trigger (phabricator_trigger) table that keeps scheduling tasks for the dead subscription"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify the subscription still exists before queueing billing work.\n$subscription = id(new PhortuneSubscriptionQuery())\n  ->setViewer(PhabricatorUser::getOmnipotentUser())\n  ->withPHIDs(array($subscription_phid))\n  ->executeOne();\nif (!$subscription) {\n  return; // do not schedule billing for a subscription that is gone\n}","typeGuard":null,"tryCatchPattern":"try {\n  // scheduling or executing subscription trigger tasks\n} catch (PhabricatorWorkerPermanentFailureException $ex) {\n  if (strpos($ex->getMessage(), 'Failed to load subscription') !== false) {\n  // orphaned trigger: remove the trigger row instead of re-queueing\n  }\n}","preventionTips":["Delete or cancel subscriptions before dropping their rows","When re-queuing or cloning worker tasks, re-validate referenced PHIDs first","Clean up trigger rows when subscriptions are removed programmatically"],"tags":["phabricator","phortune","subscription","worker","phid","permanent-failure"],"backgroundTag":"entity-not-found-by-id","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}