phacility/phabricator · error · PhabricatorWorkerPermanentFailureException

Worker has invalid task ID ("%s").

Error message

Worker has invalid task ID ("%s").

What it means

loadTask() loads the PhabricatorWorkerBulkTask row by the taskID from worker task data; a failed load (no row with that ID) permanently fails the worker task. It is the task-level counterpart of the invalid-job-ID error and likewise indicates the referenced row is gone or the ID is wrong.

Source

Thrown at src/infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobWorker.php:53

  final protected function loadJob() {
    $id = $this->getJobID();
    $job = id(new PhabricatorWorkerBulkJobQuery())
      ->setViewer(PhabricatorUser::getOmnipotentUser())
      ->withIDs(array($id))
      ->executeOne();
    if (!$job) {
      throw new PhabricatorWorkerPermanentFailureException(
        pht('Worker has invalid job ID ("%s").', $id));
    }
    return $job;
  }

  final protected function loadTask() {
    $id = $this->getTaskID();
    $task = id(new PhabricatorWorkerBulkTask())->load($id);
    if (!$task) {
      throw new PhabricatorWorkerPermanentFailureException(
        pht('Worker has invalid task ID ("%s").', $id));
    }
    return $task;
  }

  final protected function loadActor(PhabricatorWorkerBulkJob $job) {
    $actor_phid = $job->getAuthorPHID();
    $actor = id(new PhabricatorPeopleQuery())
      ->setViewer(PhabricatorUser::getOmnipotentUser())
      ->withPHIDs(array($actor_phid))
      ->executeOne();
    if (!$actor) {
      throw new PhabricatorWorkerPermanentFailureException(
        pht('Worker has invalid actor PHID ("%s").', $actor_phid));
    }

    $can_edit = PhabricatorPolicyFilter::hasCapability(
      $actor,

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Verify the bulk task row exists (phabricator_worker_bulk_task table) for the ID in the message.
  2. If the surrounding job is still alive, re-queue its work through the bulk job UI rather than re-inserting rows by hand.
  3. If the job was abandoned, dispose of the failed worker task — the permanent failure is expected.
Defensive patterns

Strategy: try-catch

Validate before calling

$bulk_task = id(new PhabricatorWorkerBulkTask())->load($task_id);
if (!$bulk_task) {
  // do not queue or retry the task worker
}

Try / catch

try {
  // run the bulk task worker
} catch (PhabricatorWorkerPermanentFailureException $ex) {
  // expected when the bulk task row is gone: log and archive
}

Prevention

When it happens

Trigger: The bulk task row was deleted before the worker ran; a partial database restore kept the worker task but dropped the bulk task rows; taskID corrupted in the worker task data.

Common situations: Cleanup scripts removing bulk task rows while worker tasks remain queued; restores from backup; manual worker-table surgery.

Related errors


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