phacility/phabricator · error · Exception
Commit "%s" is not a reachable ancestor of "%s".
Error message
Commit "%s" is not a reachable ancestor of "%s".
What it means
Exception from PhabricatorGitGraphStream: the stream finished parsing 'git log' output without ever reaching the requested commit, and the stream was started from a specific start commit. The requested commit is not reachable from the history the stream walked — the repository state does not match the expectation that the commit is an ancestor of the start commit.
Source
Thrown at src/applications/repository/daemon/PhabricatorGitGraphStream.php:88
list($hash, $parents, $epoch) = explode("\1", $line);
if ($parents) {
$parents = explode(' ', $parents);
} else {
// First commit.
$parents = array();
}
$this->dates[$hash] = $epoch;
$this->parents[$hash] = $parents;
if ($this->isParsed($commit)) {
return;
}
}
if ($this->startCommit !== null) {
throw new Exception(
pht(
'Commit "%s" is not a reachable ancestor of "%s".',
$commit,
$this->startCommit));
} else {
throw new Exception(
pht(
'Commit "%s" is not a reachable ancestor of any ref.',
$commit));
}
}
private function isParsed($commit) {
return isset($this->dates[$commit]);
}
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Verify the ancestry in the repository mirror: git merge-base --is-ancestor <commit> <start> ; a non-zero exit confirms the stream cannot ever find it.
- Repair the mirror: re-pull from the primary, or re-clone if history was rewritten ( Phabricator repository hosting 'Destroy/Reclone' path), ensuring a full (non-shallow) clone.
- If the commit is genuinely unrelated (different branch), correct the caller that assumed ancestry and pass the right start commit/ref.
- Run git fsck on the mirror to detect missing/corrupt objects, and check daemon logs for interrupted pulls that left the mirror stale.
Defensive patterns
Strategy: try-catch
Validate before calling
// Before asking the stream for a commit, verify ancestry in the mirror:
list($rc) = execx_remote(...); // conceptually:
// git merge-base --is-ancestor <commit> <start-commit>
if ($rc !== 0) { /* skip or re-pull before parsing */ } Type guard
function isReachableAncestor($repository_path, $commit, $start) {
$future = new ExecFuture('git -C %s merge-base --is-ancestor %s %s',
$repository_path, $commit, $start);
list($err) = $future->resolve();
return $err === 0;
} Try / catch
try {
$date = $stream->getCommitDate($commit);
} catch (Exception $ex) {
// log, re-pull/re-clone mirror, and re-queue the task
phlog($ex);
$this->yieldToDaemon(); // retry after repository repair
} Prevention
- Keep mirrors full clones; avoid shallow clones on hosted repos.
- Re-pull immediately after known force pushes upstream.
- Verify commit reachability with git merge-base --is-ancestor before bulk graph queries.
When it happens
Trigger: The graph stream (used by repository daemons to resolve commit dates/parents) is given a start commit and asked for a commit that git log never emits: the commit is on an unrelated branch, history was rewritten/force-pushed so the commit is no longer an ancestor, the mirror is a shallow clone, or the object is missing. Raised from the loop that fills dates/parents once log output is exhausted without isParsed() success.
Common situations: Force pushes or history rewrites in the upstream repository after Phabricator parsed older data; shallow/incomplete mirrors or interrupted pulls; querying a commit hash that exists in the object store but is dangling (not reachable from any ref walked); races where refs moved mid-parse.
Related errors
- Commit "%s" is not a reachable ancestor of any ref.
- No such %s '%s' in repository!
- Unknown commit "%s"!
- Commit "%s" (with PHID "%s") is no longer reachable from any
- Failed to parse line '%s'.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/ad8480d89e55fd50.
Report an issue: GitHub.