phacility/phabricator · error · Exception

Failed to load comment "%s".

Error message

Failed to load comment "%s".

What it means

Thrown when processing an inline-comment request whose `replyToCommentPHID` parameter does not resolve to a loadable comment. The controller loads the parent comment to clone its location (changeset ID, line, etc.) so replies stay anchored to the original; if the PHID fails to load — nonexistent, deleted, or invisible to the viewer — the controller throws. loadCommentByPHID runs through the subclass's query with the acting viewer, so policy filtering applies.

Source

Thrown at src/infrastructure/diff/PhabricatorInlineCommentController.php:384

    // NOTE: This isn't necessarily a DifferentialChangeset ID, just an
    // application identifier for the changeset. In Diffusion, it's a Path ID.
    $this->changesetID = $request->getInt('changesetID');

    $this->isNewFile = (int)$request->getBool('is_new');
    $this->isOnRight = $request->getBool('on_right');
    $this->lineNumber = $request->getInt('number');
    $this->lineLength = $request->getInt('length');
    $this->commentID = $request->getInt('id');
    $this->operation = $request->getStr('op');
    $this->renderer = $request->getStr('renderer');
    $this->replyToCommentPHID = $request->getStr('replyToCommentPHID');

    if ($this->getReplyToCommentPHID()) {
      $reply_phid = $this->getReplyToCommentPHID();
      $reply_comment = $this->loadCommentByPHID($reply_phid);
      if (!$reply_comment) {
        throw new Exception(
          pht('Failed to load comment "%s".', $reply_phid));
      }

      // When replying, force the new comment into the same location as the
      // old comment. If we don't do this, replying to a ghost comment from
      // diff A while viewing diff B can end up placing the two comments in
      // different places while viewing diff C, because the porting algorithm
      // makes a different decision. Forcing the comments to bind to the same
      // place makes sure they stick together no matter which diff is being
      // viewed. See T10562 for discussion.

      $this->changesetID = $reply_comment->getChangesetID();
      $this->isNewFile = $reply_comment->getIsNewFile();
      $this->lineNumber = $reply_comment->getLineNumber();
      $this->lineLength = $reply_comment->getLineLength();
    }
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Reload the diff/review page and reply from the fresh comment thread so the client sends a current PHID
  2. Verify the parent comment still exists and is visible to the replying user
  3. Clear stale comment drafts (feedback icons / transaction drafts) if the browser keeps replaying an old reply target
Defensive patterns

Strategy: validation

Validate before calling

// Client-side, before submitting a reply
if (!phidRegexpMatch(replyToCommentPHID)) {
  // drop the stale reply target and submit as a fresh comment instead
  delete replyToCommentPHID from form payload;
}

Type guard

function isPhid($value) {
  return is_string($value)
    && (bool) preg_match('/^PHID-[A-Z]{4}-[a-z0-9]{8,}$/', $value);
}

Prevention

When it happens

Trigger: POSTing an inline reply where `replyToCommentPHID` is a stale, deleted, or malformed PHID; replying to a ghost comment whose original was deleted; a draft replay in the browser carrying an outdated PHID from local storage; requests forged or hand-built with an arbitrary PHID string.

Common situations: Long-lived review pages where the parent comment was removed before the reply was submitted; multi-user reviews where policy hides the parent from the replier; browser extensions or automation that cache form state across days.

Related errors


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