{"record":{"id":"0bd6cff3a759f53f","repo":"phacility/phabricator","slug":"found-unexpected-job-status-s","errorCode":null,"errorMessage":"Found unexpected job status (\"%s\").","messagePattern":"Found unexpected job status \\(\"(.+?)\"\\)\\.","errorType":"exception","errorClass":"PhabricatorWorkerPermanentFailureException","httpStatus":null,"severity":"error","filePath":"src/infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobCreateWorker.php","lineNumber":19,"sourceCode":"<?php\n\nfinal class PhabricatorWorkerBulkJobCreateWorker\n  extends PhabricatorWorkerBulkJobWorker {\n\n  protected function doWork() {\n    $lock = $this->acquireJobLock();\n\n    $job = $this->loadJob();\n    $actor = $this->loadActor($job);\n\n    $status = $job->getStatus();\n    switch ($status) {\n      case PhabricatorWorkerBulkJob::STATUS_WAITING:\n        // This is what we expect. Other statuses indicate some kind of race\n        // is afoot.\n        break;\n      default:\n        throw new PhabricatorWorkerPermanentFailureException(\n          pht(\n            'Found unexpected job status (\"%s\").',\n            $status));\n    }\n\n    $tasks = $job->createTasks();\n    foreach ($tasks as $task) {\n      $task->save();\n    }\n\n    $this->updateJobStatus(\n      $job,\n      PhabricatorWorkerBulkJob::STATUS_RUNNING);\n\n    $lock->unlock();\n\n    foreach ($tasks as $task) {\n      PhabricatorWorker::scheduleTask(","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobCreateWorker.php#L1-L37","documentation":"PhabricatorWorkerBulkJobCreateWorker performs the queued setup step for a bulk job and requires the job to still be in STATUS_WAITING; any other status indicates a race (the job already advanced, was cancelled, or is being processed elsewhere) and the task is permanently failed rather than retried. This is Phabricator's guard against double-executing job setup and its side effects.","triggerScenarios":"Two create-task workers racing on one bulk job (duplicate queue entry); the job being confirmed, cancelled or otherwise moved past WAITING between queueing and execution; manually re-queueing a job's create task after it already ran.","commonSituations":"Queue duplication after a database restore or manual worker-table edits; operators 'retrying' a stuck bulk job by cloning its tasks; heavy taskmaster load exposing races between duplicate tasks.","solutions":["Check the bulk job's current status in the UI or database; if it already progressed past WAITING, the failure is the guard working correctly and the duplicate task can be discarded.","If the job is genuinely stuck and this was its only create task, re-run the job from the bulk job UI so a fresh create task is queued.","Never hand-insert or duplicate worker tasks for bulk jobs."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  // execute the bulk job create worker\n} catch (PhabricatorWorkerPermanentFailureException $ex) {\n  // terminal: mark the task garbage, inspect the job status, never blind-requeue\n}","preventionTips":["Do not duplicate or hand-requeue bulk job worker tasks.","Drive bulk jobs through their UI lifecycle (confirm/queue) only.","Treat this failure on duplicate tasks as expected after queue duplication."],"tags":["phabricator","bulk-jobs","worker-queue","race-condition"],"backgroundTag":"invalid-state-transition","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}