{"record":{"id":"cc821a1a76032bf0","repo":"phacility/phabricator","slug":"changeset-id-s-is-part-of-diff-id-s-but-tha","errorCode":null,"errorMessage":"Changeset ID \"%s\" is part of diff ID \"%s\", but that diff is attached to revision \"%s\", not revision \"%s\".","messagePattern":"Changeset ID \"(.+?)\" is part of diff ID \"(.+?)\", but that diff is attached to revision \"(.+?)\", not revision \"(.+?)\"\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/differential/controller/DifferentialInlineCommentEditController.php","lineNumber":54,"sourceCode":"    $changeset_id = $this->getChangesetID();\n    $viewer = $this->getViewer();\n\n    $revision = $this->loadRevision();\n\n    $changeset = id(new DifferentialChangesetQuery())\n      ->setViewer($viewer)\n      ->withIDs(array($changeset_id))\n      ->executeOne();\n    if (!$changeset) {\n      throw new Exception(\n        pht(\n          'Invalid changeset ID \"%s\"!',\n          $changeset_id));\n    }\n\n    $diff = $changeset->getDiff();\n    if ($diff->getRevisionID() != $revision->getID()) {\n      throw new Exception(\n        pht(\n          'Changeset ID \"%s\" is part of diff ID \"%s\", but that diff '.\n          'is attached to revision \"%s\", not revision \"%s\".',\n          $changeset_id,\n          $diff->getID(),\n          $diff->getRevisionID(),\n          $revision->getID()));\n    }\n\n    return id(new DifferentialInlineComment())\n      ->setRevision($revision)\n      ->setChangesetID($changeset_id);\n  }\n\n  protected function loadCommentForDone($id) {\n    $viewer = $this->getViewer();\n\n    $inline = $this->loadCommentByID($id);","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/differential/controller/DifferentialInlineCommentEditController.php#L36-L72","documentation":"Even when the revision and the changeset both exist, the controller verifies they belong together: the changeset's diff must be attached to the same revision. A mismatch throws this error. The check protects against stale parameter mixing and cross-revision request construction.","triggerScenarios":"Mixing a changeset id from revision A with the revision id of revision B in one inline-comment request — stale forms, request replay, or hand-built parameters.","commonSituations":"Two revisions open in parallel with a copy-pasted URL; automation that caches changeset IDs and reuses them across revisions.","solutions":["Always derive both the revision id and the changeset id from the same revision/diff view.","Re-render the comment form after the revision updates, so it embeds current IDs.","In automation, fetch the changesets of the specific revision and use only those IDs."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before posting an inline comment, confirm the changeset id belongs to the\n// revision being commented on\n$changeset_ids = array(); // ids rendered with the current diff view\nif (!in_array($changeset_id, $changeset_ids, true)) {\n  throw new InvalidArgumentException(\n    'Changeset does not belong to this revision.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  // submit the inline comment\n} catch (Exception $ex) {\n  if (preg_match('/is part of diff ID/', $ex->getMessage())) {\n    // mixed ids: refresh both from the same revision view and resubmit\n  } else {\n    throw $ex;\n  }\n}","preventionTips":["Derive the revision id and the changeset id from the same diff view.","Re-render comment forms after revision updates so embedded ids stay current.","Do not reuse captured changeset ids across revisions."],"tags":["phabricator","differential","inline-comment","entity-mismatch"],"backgroundTag":"entity-mismatch","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}