phacility/phabricator · error · PhabricatorWorkerPermanentFailureException

Associated hook ("%s") for webhook request ("%s") is disable

Error message

Associated hook ("%s") for webhook request ("%s") is disabled.

What it means

Before making the HTTP call, the worker checks the hook with isDisabled(); a disabled hook causes the request to be marked failed with ERRORTYPE_HOOK / ERROR_DISABLED and the task to permanently fail. Hooks are disabled manually from the Webhooks UI or automatically after too many consecutive failures, so no further calls are made.

Source

Thrown at src/applications/herald/worker/HeraldWebhookWorker.php:52

    // 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;
    }

    $hook = $request->getWebhook();

    if ($hook->isDisabled()) {
      $this->failRequest(
        $request,
        HeraldWebhookRequest::ERRORTYPE_HOOK,
        HeraldWebhookRequest::ERROR_DISABLED);
      throw new PhabricatorWorkerPermanentFailureException(
        pht(
          'Associated hook ("%s") for webhook request ("%s") is disabled.',
          $hook->getPHID(),
          $request_phid));
    }

    $uri = $hook->getWebhookURI();
    try {
      PhabricatorEnv::requireValidRemoteURIForFetch(
        $uri,
        array(
          'http',
          'https',
        ));
    } catch (Exception $ex) {
      $this->failRequest(
        $request,
        HeraldWebhookRequest::ERRORTYPE_HOOK,

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Re-enable the hook from the Webhooks console (/webhook/), then fire a fresh test with './bin/herald call-webhook --id <hook> --object <object>'.
  2. Check the hook's error log to see why it was disabled (usually repeated failures) and fix the endpoint first.
  3. If the hook should stay disabled, acknowledge the permanent failures -- no delivery is intended.
Defensive patterns

Strategy: validation

Validate before calling

// Before queueing or firing, check the hook state:
if ($hook->isDisabled()) {
  throw new RuntimeException(
    'Webhook '.$hook->getID().' is disabled; enable it in /webhook/ first.');
}

Type guard

function heraldWebhookIsCallable(HeraldWebhook $hook) {
  return !$hook->isDisabled();
}

Prevention

When it happens

Trigger: A webhook request was queued while the hook was enabled, then the hook was disabled before the task ran; the hook was auto-disabled by the failure threshold with old queued tasks still pending.

Common situations: Hook auto-disabled during a receiver outage while a queue backlog existed; an admin disabling a noisy hook without draining its queue.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/e2cec6b4468332b8. Report an issue: GitHub.