phacility/phabricator · error · PhabricatorWorkerPermanentFailureException
Found unexpected task status ("%s").
Error message
Found unexpected task status ("%s"). What it means
PhabricatorWorkerBulkJobTaskWorker executes one unit of a bulk job and requires the bulk task row to still be in STATUS_WAITING when it starts (checked while holding a per-task global lock). A different status means the task already ran, is running elsewhere, or was completed — so the worker permanently fails instead of re-executing side effects.
Source
Thrown at src/infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobTaskWorker.php:16
<?php
final class PhabricatorWorkerBulkJobTaskWorker
extends PhabricatorWorkerBulkJobWorker {
protected function doWork() {
$lock = $this->acquireTaskLock();
$task = $this->loadTask();
$status = $task->getStatus();
switch ($task->getStatus()) {
case PhabricatorWorkerBulkTask::STATUS_WAITING:
// This is what we expect.
break;
default:
throw new PhabricatorWorkerPermanentFailureException(
pht(
'Found unexpected task status ("%s").',
$status));
}
$task
->setStatus(PhabricatorWorkerBulkTask::STATUS_RUNNING)
->save();
$lock->unlock();
$job = $this->loadJob();
$actor = $this->loadActor($job);
try {
$job->runTask($actor, $task);
$status = PhabricatorWorkerBulkTask::STATUS_DONE;
} catch (Exception $ex) {View on GitHub (pinned to 5720a38cfe)
Solutions
- Check the bulk task's status; if it is RUNNING or DONE, the failure is the guard working — ignore the duplicate.
- If a task is stuck in RUNNING after a crash, resolve the stale row via the worker management workflows before retrying.
- Do not re-queue bulk task rows by hand.
Defensive patterns
Strategy: try-catch
Try / catch
try {
// execute the bulk task worker
} catch (PhabricatorWorkerPermanentFailureException $ex) {
// terminal: check the bulk task status; ignore duplicates of DONE/RUNNING tasks
} Prevention
- Never clone bulk task rows or use bin/worker retry on bulk tasks casually.
- Resolve stale RUNNING rows via the worker management workflows after daemon crashes.
- Treat this failure on duplicate rows as the guard working as designed.
When it happens
Trigger: Duplicate task rows for one bulk task; a task re-queued after completion; a stale RUNNING row from a crashed daemon being executed again.
Common situations: Database restores that duplicate worker rows; aggressive manual use of bin/worker retry; crashed taskmasters leaving stale rows that later get re-executed after lease expiry.
Related errors
- Found unexpected job status ("%s").
- Worker has no job ID.
- Worker has no task ID.
- Worker has invalid job ID ("%s").
- Worker has invalid task ID ("%s").
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/dfd05e5f0d2b2052.
Report an issue: GitHub.