phacility/phabricator · error · PhabricatorWorkerPermanentFailureException
Webhook request ("%s") is not in "%s" status (actual status
Error message
Webhook request ("%s") is not in "%s" status (actual status is "%s"). Declining call to hook. What it means
The webhook worker only delivers a request whose status is STATUS_QUEUED; any other status means the request was already sent or failed, so the task permanently fails instead of double-calling the hook. This almost always means the same request was processed twice -- a duplicate queued task or a retry that raced a completed attempt.
Source
Thrown at src/applications/herald/worker/HeraldWebhookWorker.php:26
$data = $this->getTaskData();
$request_phid = idx($data, 'webhookRequestPHID');
$request = id(new HeraldWebhookRequestQuery())
->setViewer($viewer)
->withPHIDs(array($request_phid))
->executeOne();
if (!$request) {
throw new PhabricatorWorkerPermanentFailureException(
pht(
'Unable to load webhook request ("%s"). It may have been '.
'garbage collected.',
$request_phid));
}
$status = $request->getStatus();
if ($status !== HeraldWebhookRequest::STATUS_QUEUED) {
throw new PhabricatorWorkerPermanentFailureException(
pht(
'Webhook request ("%s") is not in "%s" status (actual '.
'status is "%s"). Declining call to hook.',
$request_phid,
HeraldWebhookRequest::STATUS_QUEUED,
$status));
}
// If we're in silent mode, permanently fail the webhook request and then
// return to complete this task.
if (PhabricatorEnv::getEnvConfig('phabricator.silent')) {
$this->failRequest(
$request,
HeraldWebhookRequest::ERRORTYPE_HOOK,
HeraldWebhookRequest::ERROR_SILENT);
return;
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Inspect the request in the Webhooks UI -- it already has a terminal status, so no further action is needed for that request.
- If you need another delivery, fire a fresh request via './bin/herald call-webhook --id <hook> --object <object>'.
- Let the duplicate task die: permanent failure removes it from the queue without retries.
Defensive patterns
Strategy: validation
Validate before calling
// In any custom processor, re-check status before acting on a request:
$request = id(new HeraldWebhookRequestQuery())
->setViewer($viewer)
->withPHIDs(array($request_phid))
->executeOne();
if (!$request || $request->getStatus() !== HeraldWebhookRequest::STATUS_QUEUED) {
return; // already handled elsewhere; skip instead of double-delivering
} Try / catch
try {
// process queued webhook request
} catch (PhabricatorWorkerPermanentFailureException $ex) {
// duplicate/stale task: the request already reached a terminal status
phlog($ex->getMessage());
} Prevention
- Never assume a dequeued task is the only attempt for a request; always re-read its status.
- Make webhook handling idempotent keyed on the request PHID.
When it happens
Trigger: Two worker tasks enqueued for the same request PHID; a task retried (lease expiry) after the first attempt already updated the request to SENT/FAILED; manual status changes on the request row.
Common situations: Queue backlog replayed after a restore; duplicate task insertion during high load; a retried timeout task whose first attempt actually succeeded.
Related errors
- Unable to load webhook request ("%s"). It may have been garb
- Associated hook ("%s") for webhook request ("%s") is disable
- Unable to load object ("%s") for webhook request ("%s").
- Webhook request ("%s", to "%s") failed (%s / %s). The reques
- Webhook request ("%s", to "%s") failed (%s / %s). The reques
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/12fca9509e383e00.
Report an issue: GitHub.