{"record":{"id":"7694532b13e0b287","repo":"phacility/phabricator","slug":"err-bad-diff-769453","errorCode":"ERR_BAD_DIFF","errorMessage":"ERR_BAD_DIFF","messagePattern":"ERR_BAD_DIFF","errorType":"error_code","errorClass":"ConduitException","httpStatus":null,"severity":"error","filePath":"src/applications/differential/conduit/DifferentialGetDiffConduitAPIMethod.php","lineNumber":62,"sourceCode":"      'ERR_BAD_DIFF' => pht('No such diff exists.'),\n    );\n  }\n\n  protected function execute(ConduitAPIRequest $request) {\n    $diff_id = $request->getValue('diff_id');\n\n    // If we have a revision ID, we need the most recent diff. Figure that out\n    // without loading all the attached data.\n    $revision_id = $request->getValue('revision_id');\n    if ($revision_id) {\n      $diffs = id(new DifferentialDiffQuery())\n        ->setViewer($request->getUser())\n        ->withRevisionIDs(array($revision_id))\n        ->execute();\n      if ($diffs) {\n        $diff_id = head($diffs)->getID();\n      } else {\n        throw new ConduitException('ERR_BAD_DIFF');\n      }\n    }\n\n    $diff = null;\n    if ($diff_id) {\n      $diff = id(new DifferentialDiffQuery())\n        ->setViewer($request->getUser())\n        ->withIDs(array($diff_id))\n        ->needChangesets(true)\n        ->executeOne();\n    }\n\n    if (!$diff) {\n      throw new ConduitException('ERR_BAD_DIFF');\n    }\n\n    return $diff->getDiffDict();\n  }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/differential/conduit/DifferentialGetDiffConduitAPIMethod.php#L44-L80","documentation":"Thrown by the differential.getdiff Conduit method in its revision branch. When revision_id is supplied, the method queries all diffs attached to that revision (withRevisionIDs) and takes the newest; if the query returns no diffs at all - wrong ID, revision invisible to the viewer, or a revision with zero attached diffs - ConduitException('ERR_BAD_DIFF') is thrown before the diff is loaded.","triggerScenarios":"Calling differential.getdiff with a revision_id that does not exist, is 'D'-prefixed, is invisible to the caller, or names a revision that has no diffs yet.","commonSituations":"Automation fetching the current diff for a revision number parsed from a branch name; restricted spaces hiding the revision; passing a PHID instead of the integer ID.","solutions":["Verify the revision exists and is visible via differential.query before calling","If you already know the diff, pass diff_id directly and skip the revision lookup","Send revision_id as a bare integer","Catch ERR_BAD_DIFF distinctly: here it means 'no diffs for revision', not necessarily a bad diff id"],"exampleFix":"// before\n$params = array('revision_id' => 'D77');\n\n// after\n$params = array('revision_id' => 77);","handlingStrategy":"try-catch","validationCode":"// Confirm the revision has diffs before fetching.\n$found = $client->callMethodSynchronous('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  $dict = $client->callMethodSynchronous('differential.getdiff',\n    array('revision_id' => (int)$rev_id));\n} catch (ConduitClientException $ex) {\n  if ($ex->getErrorCode() === 'ERR_BAD_DIFF') {\n    // revision unknown/invisible or has no diffs\n  } else {\n    throw $ex;\n  }\n}","preventionTips":["Send bare integer revision ids","When you know the diff, pass diff_id and skip the revision branch","Pre-check visibility with differential.query for IDs from untrusted sources"],"tags":["phabricator","conduit","differential","diff","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}