{"record":{"id":"adf281f7275325b6","repo":"phacility/phabricator","slug":"unable-to-load-webhook-request-s-it-may-have","errorCode":null,"errorMessage":"Unable to load webhook request (\"%s\"). It may have been garbage collected.","messagePattern":"Unable to load webhook request \\(\"(.+?)\"\\)\\. It may have been garbage collected\\.","errorType":"exception","errorClass":"PhabricatorWorkerPermanentFailureException","httpStatus":null,"severity":"error","filePath":"src/applications/herald/worker/HeraldWebhookWorker.php","lineNumber":17,"sourceCode":"<?php\n\nfinal class HeraldWebhookWorker\n  extends PhabricatorWorker {\n\n  protected function doWork() {\n    $viewer = PhabricatorUser::getOmnipotentUser();\n\n    $data = $this->getTaskData();\n    $request_phid = idx($data, 'webhookRequestPHID');\n\n    $request = id(new HeraldWebhookRequestQuery())\n      ->setViewer($viewer)\n      ->withPHIDs(array($request_phid))\n      ->executeOne();\n    if (!$request) {\n      throw new PhabricatorWorkerPermanentFailureException(\n        pht(\n          'Unable to load webhook request (\"%s\"). It may have been '.\n          'garbage collected.',\n          $request_phid));\n    }\n\n    $status = $request->getStatus();\n    if ($status !== HeraldWebhookRequest::STATUS_QUEUED) {\n      throw new PhabricatorWorkerPermanentFailureException(\n        pht(\n          'Webhook request (\"%s\") is not in \"%s\" status (actual '.\n          'status is \"%s\"). Declining call to hook.',\n          $request_phid,\n          HeraldWebhookRequest::STATUS_QUEUED,\n          $status));\n    }\n\n    // If we're in silent mode, permanently fail the webhook request and then","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/herald/worker/HeraldWebhookWorker.php#L1-L35","documentation":"The webhook worker task carries a 'webhookRequestPHID' in its task data; when HeraldWebhookQuery cannot load that row, the task permanently fails with PhabricatorWorkerPermanentFailureException. The most common cause is the request row being garbage collected while the task was still queued, so the work it describes no longer exists.","triggerScenarios":"A queued webhook call task executes after its herald_webhook_request row was garbage collected; worker queue data surviving a database restore that dropped request rows; the request row was deleted manually.","commonSituations":"Daemon downtime plus GC catching up; restoring a DB backup while the worker queue retains old tasks; aggressive webhook-request retention on a slow queue.","solutions":["Treat the permanent failure as expected cleanup: the request is gone, so no delivery is possible; acknowledge/alert rather than retry.","If delivery still matters, re-fire a fresh request with './bin/herald call-webhook --id <hook> --object <object>'.","If this recurs, review webhook-request garbage collection retention so live queued requests are not collected.","Prune stale queued tasks after DB restores so they do not execute against missing rows."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// When queueing webhook work yourself, only queue for requests that exist:\n$request = id(new HeraldWebhookRequestQuery())\n  ->setViewer($viewer)\n  ->withPHIDs(array($request_phid))\n  ->executeOne();\nif ($request) {\n  PhabricatorWorker::scheduleTask(\n    'HeraldWebhookWorker',\n    array('webhookRequestPHID' => $request->getPHID()));\n}","typeGuard":null,"tryCatchPattern":"// In daemon/tooling that processes worker results, treat permanent failures as terminal:\ntry {\n  $task->executeTask();\n} catch (PhabricatorWorkerPermanentFailureException $ex) {\n  // Request row is gone (e.g. garbage collected); log and move on. Never retry.\n  phlog($ex->getMessage());\n}","preventionTips":["Keep webhook-request GC retention longer than your worst-case queue backlog.","After DB restores, prune stale queued tasks before restarting daemons.","Monitor permanent-failure counts so silently dropped deliveries are visible."],"tags":["herald","webhook","phabricator","worker","daemons","garbage-collection"],"backgroundTag":"record-garbage-collected","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}