phacility/phabricator · error · Exception

Invalid changeset ID "%s"!

Error message

Invalid changeset ID "%s"!

What it means

After the revision resolves, the controller loads the changeset named by the changeset id. A null, wrong, or deleted changeset ID throws 'Invalid changeset ID'. The most common source is a stale page that still references changesets from an older diff of the revision.

Source

Thrown at src/applications/differential/controller/DifferentialInlineCommentEditController.php:46

    }

    return $revision;
  }

  protected function createComment() {
    // Verify revision and changeset correspond to actual objects, and are
    // connected to one another.
    $changeset_id = $this->getChangesetID();
    $viewer = $this->getViewer();

    $revision = $this->loadRevision();

    $changeset = id(new DifferentialChangesetQuery())
      ->setViewer($viewer)
      ->withIDs(array($changeset_id))
      ->executeOne();
    if (!$changeset) {
      throw new Exception(
        pht(
          'Invalid changeset ID "%s"!',
          $changeset_id));
    }

    $diff = $changeset->getDiff();
    if ($diff->getRevisionID() != $revision->getID()) {
      throw new Exception(
        pht(
          'Changeset ID "%s" is part of diff ID "%s", but that diff '.
          'is attached to revision "%s", not revision "%s".',
          $changeset_id,
          $diff->getID(),
          $diff->getRevisionID(),
          $revision->getID()));
    }

    return id(new DifferentialInlineComment())

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Reload the revision and diff view, then re-submit the comment.
  2. Ensure the changeset id comes from the same diff you are viewing.
  3. In automation, resolve changeset IDs from the current diff via the API, never from cached pages.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  // submit the inline comment with revision id + changeset id
} catch (Exception $ex) {
  if (preg_match('/Invalid changeset ID/', $ex->getMessage())) {
    // stale view: reload the diff and resubmit with a current changeset id
  } else {
    throw $ex;
  }
}

Prevention

When it happens

Trigger: Inline comment requests whose changeset id does not exist or is invisible: posting from a page rendered before the diff was replaced or deleted, or constructing requests manually.

Common situations: Commenting from a stale diff view after the author updated the revision; automation replaying captured inline-comment requests against new revisions.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/a4a7a42011af332a. Report an issue: GitHub.