phacility/phabricator · error · PhabricatorWorkerPermanentFailureException
Worker has no task ID.
Error message
Worker has no task ID.
What it means
Bulk task workers identify the row they must process via the 'taskID' key of the worker task data; getTaskID() permanently fails the task when the key is missing or falsy. As with jobID, core always populates it, so this points at custom queueing code omitting the key.
Source
Thrown at src/infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobWorker.php:30
return PhabricatorGlobalLock::newLock('bulktask.'.$this->getTaskID())
->lock(15);
}
final protected function getJobID() {
$data = $this->getTaskData();
$id = idx($data, 'jobID');
if (!$id) {
throw new PhabricatorWorkerPermanentFailureException(
pht('Worker has no job ID.'));
}
return $id;
}
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;
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Schedule task workers with array('taskID' => $task->getID(), 'jobID' => $task->getJobID()).
- Queue bulk tasks through the job pipeline rather than scheduleTask() directly.
- Mirror core's task-data keys exactly in any custom code.
Example fix
// before
PhabricatorWorker::scheduleTask(
'PhabricatorWorkerBulkJobTaskWorker',
array('jobID' => $job->getID()));
// after
PhabricatorWorker::scheduleTask(
'PhabricatorWorkerBulkJobTaskWorker',
array(
'jobID' => $job->getID(),
'taskID' => $bulk_task->getID(),
)); Defensive patterns
Strategy: validation
Validate before calling
if (!idx($task_data, 'taskID')) {
throw new InvalidArgumentException(
'Bulk task worker data requires a taskID.');
}
PhabricatorWorker::scheduleTask($bulk_task_worker_class, $task_data); Type guard
function bulk_task_data_has_task_id($data) {
return is_array($data) && !empty($data['taskID']);
} Prevention
- Queue task workers with both 'taskID' and 'jobID' set.
- Mirror core's task-data keys exactly in custom schedulers.
- Add a scheduling helper so the keys cannot be forgotten.
When it happens
Trigger: Scheduling PhabricatorWorkerBulkJobTaskWorker (or a subclass) with a data array lacking 'taskID'; the lock name itself (bulktask.<taskID>) is even derived from this value.
Common situations: Custom schedulers that copy the create-worker's data shape (jobID only) when queuing task workers; refactors that dropped the key.
Related errors
- Worker has no job ID.
- No "%s" in task data.
- Expected task data to be a dictionary.
- Found unexpected job status ("%s").
- Found unexpected task status ("%s").
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/ce8a54416a20a393.
Report an issue: GitHub.