{"record":{"id":"cbe267f1e85bae3b","repo":"phacility/phabricator","slug":"unable-to-load-object-s-for-webhook-request","errorCode":null,"errorMessage":"Unable to load object (\"%s\") for webhook request (\"%s\").","messagePattern":"Unable to load object \\(\"(.+?)\"\\) for webhook request \\(\"(.+?)\"\\)\\.","errorType":"exception","errorClass":"PhabricatorWorkerPermanentFailureException","httpStatus":null,"severity":"error","filePath":"src/applications/herald/worker/HeraldWebhookWorker.php","lineNumber":93,"sourceCode":"          'fetch URI: %s',\n          $hook->getPHID(),\n          $request_phid,\n          $ex->getMessage()));\n    }\n\n    $object_phid = $request->getObjectPHID();\n\n    $object = id(new PhabricatorObjectQuery())\n      ->setViewer($viewer)\n      ->withPHIDs(array($object_phid))\n      ->executeOne();\n    if (!$object) {\n      $this->failRequest(\n        $request,\n        HeraldWebhookRequest::ERRORTYPE_HOOK,\n        HeraldWebhookRequest::ERROR_OBJECT);\n\n      throw new PhabricatorWorkerPermanentFailureException(\n        pht(\n          'Unable to load object (\"%s\") for webhook request (\"%s\").',\n          $object_phid,\n          $request_phid));\n    }\n\n    $xaction_query = PhabricatorApplicationTransactionQuery::newQueryForObject(\n      $object);\n    $xaction_phids = $request->getTransactionPHIDs();\n    if ($xaction_phids) {\n      $xactions = $xaction_query\n        ->setViewer($viewer)\n        ->withObjectPHIDs(array($object_phid))\n        ->withPHIDs($xaction_phids)\n        ->execute();\n      $xactions = mpull($xactions, null, 'getPHID');\n    } else {\n      $xactions = array();","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/herald/worker/HeraldWebhookWorker.php#L75-L111","documentation":"The worker loads the object the webhook request is about using PhabricatorObjectQuery as the omnipotent user (so policies are not the issue). If the row is gone, the request is marked failed with ERRORTYPE_HOOK / ERROR_OBJECT and the task permanently fails -- the payload cannot be built for a deleted object.","triggerScenarios":"The object (task, revision, etc.) was deleted between the time the Herald rule queued the webhook request and the time the worker task executed; task data references an object removed by a partial DB restore.","commonSituations":"Object deletions racing a queued webhook backlog; environments where scripts mass-delete objects while hooks are active.","solutions":["Accept the permanent failure -- the object no longer exists, so the payload cannot be sent.","If these are noise, disable the hook or its rule for object types that get deleted frequently.","Re-fire for a live object with './bin/herald call-webhook --id <hook> --object <object>'."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// When queueing webhook requests, skip objects that no longer load:\n$object = id(new PhabricatorObjectQuery())\n  ->setViewer(PhabricatorUser::getOmnipotentUser())\n  ->withPHIDs(array($object_phid))\n  ->executeOne();\nif (!$object) {\n  return; // object deleted; nothing to deliver\n}","typeGuard":null,"tryCatchPattern":"try {\n  // queue/execute webhook work for an object\n} catch (PhabricatorWorkerPermanentFailureException $ex) {\n  // object or request row disappeared; permanent, do not retry\n  phlog($ex->getMessage());\n}","preventionTips":["Expect deletions to race queued webhook tasks; treat ERROR_OBJECT permanent failures as normal.","Batch-delete objects only after draining or pausing related webhook queues if deliveries matter."],"tags":["herald","webhook","phabricator","worker","entity-not-found"],"backgroundTag":"entity-not-found","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}