phacility/phabricator · error · PhabricatorWorkerPermanentFailureException
Worker has invalid job ID ("%s").
Error message
Worker has invalid job ID ("%s"). What it means
loadJob() takes the jobID from task data and loads the PhabricatorWorkerBulkJob via an omnipotent-user query; if no row matches, the task permanently fails with this message. Because the query runs as the omnipotent user, policies can never cause this — only the row's absence (deleted job or wrong ID) can.
Source
Thrown at src/infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobWorker.php:43
final protected function getTaskID() {
$data = $this->getTaskData();
$id = idx($data, 'taskID');
if (!$id) {
throw new PhabricatorWorkerPermanentFailureException(
pht('Worker has no task ID.'));
}
return $id;
}
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())View on GitHub (pinned to 5720a38cfe)
Solutions
- Check whether the bulk job still exists (bulk job UI or the phabricator_worker_bulk_job table).
- If it was deleted intentionally, the permanent failure is correct — archive/dispose of the failed task.
- If the job should exist, restore the missing row or fix the referenced ID, then re-queue the task.
- Keep taskmaster throughput healthy so tasks do not outlive their jobs.
Defensive patterns
Strategy: try-catch
Validate before calling
$job = id(new PhabricatorWorkerBulkJobQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withIDs(array($job_id))
->executeOne();
if (!$job) {
// do not queue the worker task
} Try / catch
try {
// run the bulk worker
} catch (PhabricatorWorkerPermanentFailureException $ex) {
// expected when the job row is gone: log and archive the task
} Prevention
- Cancel bulk jobs instead of deleting them while worker tasks are queued.
- Keep taskmaster throughput healthy so tasks do not outlive jobs.
- Avoid partial restores that keep worker rows but drop job rows.
When it happens
Trigger: The bulk job was deleted before its worker task ran; jobID in the task data points at a nonexistent row after data corruption or a partial database restore that kept worker tasks but dropped job rows.
Common situations: Admins deleting queued bulk jobs; partial restores; long queue backlogs where tasks outlive the jobs they reference.
Related errors
- Worker has invalid task ID ("%s").
- Found unexpected job status ("%s").
- Found unexpected task status ("%s").
- Worker has no job ID.
- Worker has no task ID.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/20dcf188ff02c6f5.
Report an issue: GitHub.