{"record":{"id":"81e62eb98c53a0dc","repo":"phacility/phabricator","slug":"err-bad-revision","errorCode":"ERR_BAD_REVISION","errorMessage":"ERR_BAD_REVISION","messagePattern":"ERR_BAD_REVISION","errorType":"error_code","errorClass":"ConduitException","httpStatus":null,"severity":"error","filePath":"src/applications/differential/conduit/DifferentialCreateCommentConduitAPIMethod.php","lineNumber":55,"sourceCode":"\n  protected function defineErrorTypes() {\n    return array(\n      'ERR_BAD_REVISION' => pht('Bad revision ID.'),\n    );\n  }\n\n  protected function execute(ConduitAPIRequest $request) {\n    $viewer = $request->getUser();\n\n    $revision = id(new DifferentialRevisionQuery())\n      ->setViewer($viewer)\n      ->withIDs(array($request->getValue('revision_id')))\n      ->needReviewers(true)\n      ->needReviewerAuthority(true)\n      ->needActiveDiffs(true)\n      ->executeOne();\n    if (!$revision) {\n      throw new ConduitException('ERR_BAD_REVISION');\n    }\n\n    $xactions = array();\n\n    $modular_map = array(\n      'accept' => DifferentialRevisionAcceptTransaction::TRANSACTIONTYPE,\n      'reject' => DifferentialRevisionRejectTransaction::TRANSACTIONTYPE,\n      'resign' => DifferentialRevisionResignTransaction::TRANSACTIONTYPE,\n      'request_review' =>\n        DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE,\n      'rethink' => DifferentialRevisionPlanChangesTransaction::TRANSACTIONTYPE,\n    );\n\n    $action = $request->getValue('action');\n    if (isset($modular_map[$action])) {\n      $xactions[] = id(new DifferentialTransaction())\n        ->setTransactionType($modular_map[$action])\n        ->setNewValue(true);","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/differential/conduit/DifferentialCreateCommentConduitAPIMethod.php#L37-L73","documentation":"Thrown by the differential.createcomment Conduit method. It loads the revision from the revision_id parameter with a policy-filtered query that also attaches reviewers, reviewer authority, and active diffs. If no revision is visible for that ID, it throws ConduitException('ERR_BAD_REVISION') before building any comment or status-change transaction.","triggerScenarios":"Calling differential.createcomment with revision_id equal to 0, null, a nonexistent ID, a 'D'-prefixed string, or an ID whose revision the acting user cannot see under visibility policies.","commonSituations":"CI bots posting review feedback on revisions in restricted spaces; scripts reusing IDs from a stale tracking database; passing a revision PHID where the integer ID is expected; the revision was deleted or moved between the lookup and the comment call.","solutions":["Pass revision_id as a bare integer that you confirmed exists (differential.query with ids=[id])","Run the call with a conduit token whose user can see the revision's project/space policies","If the revision may have been deleted, catch ERR_BAD_REVISION and skip instead of retrying","Prefer the newer differential.revision.edit method with a comment transaction for new integrations"],"exampleFix":"// before\n$params = array(\n  'revision_id' => 'D456',\n  'message' => 'Ship it.',\n);\n\n// after\n$params = array(\n  'revision_id' => 456,\n  'message' => 'Ship it.',\n);","handlingStrategy":"try-catch","validationCode":"$found = $client->callMethodSynchronous(\n  'differential.query',\n  array('ids' => array((int)$rev_id)));\nif (!$found) {\n  throw new InvalidArgumentException('Unknown revision '.$rev_id);\n}","typeGuard":null,"tryCatchPattern":"try {\n  $client->callMethodSynchronous('differential.createcomment', $params);\n} catch (ConduitClientException $ex) {\n  if ($ex->getErrorCode() === 'ERR_BAD_REVISION') {\n    // bad or invisible revision_id: fix input, do not retry as-is\n  } else {\n    throw $ex;\n  }\n}","preventionTips":["Validate revision_id as a positive integer before building params","Use a token whose user can see the revision's space and policies","In feedback bots, catch and skip per-revision instead of aborting the batch"],"tags":["phabricator","conduit","differential","revision","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}