fix(github): pull requests missing refs/pull/N/head no longer show as not found#25947

open3
main
GitHub fork: fix/github-pr-missing-head-ref
opened6d agobyRRadu028
View on GitHubTwo-way sync enabledPR last imported 5h ago

Problem

Some open pull requests lack refs/pull/<number>/head even though GitHub returns their data. The detail and action-state queries compare the base branch against that ref, so GitHub answers with the full pull request plus one NOT_FOUND on repository.pullRequest.baseRef.compare. The GraphQL client read any all-NOT_FOUND answer as a missing resource. The panel showed "Pull request #N not found", merge and update-branch failed the same way, and the watch gave up after eight failed reads. The log said only "GitHub could not find the requested resource".

Change

  • The detail and action-state reads accept exactly that answer (HTTP 200, no other error) and keep the data GitHub sent with it. The comparison is unknown, rather than spending a second request to compare by head SHA. Merge and update-branch proceed again. The UI still does not offer Update branch while the comparison is unknown, as when GitHub cannot compare. The requested-reviewer retry from #19564 also runs when the missing ref comes with a refused reviewer.
  • isNotFoundOnly counts a NOT_FOUND as a missing resource only without a path, on a root field (with its list items), or on repository.pullRequest. A deeper one, like this comparison, is a response error.
  • GraphQL errors keep GitHub's message and path in githubErrors, now on GitHubApiNotFoundError too, so a failure like this one names its cause in the log.

The last two changes belong to the same defect: they are why a failed comparison was reported, and logged, as a missing pull request.

This is a small fix for an obvious bug, sent without an issue: an existing pull request is reported missing, and the change stays inside GitHub GraphQL error handling.

Reproduction

The affected repository is private, so names and numbers are replaced. N is the affected pull request, M an open neighbour that has both refs.

1gh api repos/<owner>/<repo>/git/ref/pull/N/head # 404, while refs/pull/N/merge exists
2
3query { repository(owner: "<owner>", name: "<repo>") { pullRequest(number: N) {
4 headRefOid baseRef { compare(headRef: "refs/pull/N/head") { behindBy } } } } }
5
6data.repository.pullRequest is present, compare is null, and errors is:
7[{"type":"NOT_FOUND","path":["repository","pullRequest","baseRef","compare"],
8 "message":"Could not resolve head ref 'refs/pull/N/head'."}]

Verification

Linux, Node 24, from packages/source-control-github. Using the gh credential, GitHubPullRequestProvider.getChangeRequest returned:

1main {"number":N,"ok":false,"reason":"not-found","detail":"GitHub could not find the requested resource, or the credential cannot see it."}
2 {"number":M,"ok":true,"state":"open","baseComparison":"up-to-date","behindBy":0}
3branch {"number":N,"ok":true,"state":"open","baseComparison":"unknown","behindBy":null}
4 {"number":M,"ok":true,"state":"open","baseComparison":"up-to-date","behindBy":0}

vp test run src/server/GitHubPullRequestApi.test.ts src/server/gitHubGraphQlClient.test.ts passes 124 tests. Reverting the three production files to main makes 10 of them fail. vp run check:changed passes.

Not verified: the panel and the watch in a running app, merge and update-branch against the real pull request (tests only), and GitHub Enterprise.

Models: Claude Opus 5.5 (implementation), GPT-6.1-Sol (independent review). Harness: Claude Code through T3 Code.

🤖 Generated with Claude Code

Checks

2 failing · 20 successful · 7 skipped
Some checks failed

Failing2

8d04b0c

Added 1 commit

  • fix(github): pull requests missing refs/pull/N/head no longer show as not foundafba1ef
Synced from GitHub

Approvability

Verdict: Approved at afba1ef

Macroscope's review found this PR approvable — This is a focused GitHub GraphQL error-handling fix that preserves existing pull-request data when only the synthetic head ref is missing, while retaining diagnostics for genuine failures. The production changes are narrowly scoped and covered by targeted regression tests.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

External image Recent review info
External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between 59737e855d79d5d33ed12428ccdd0efb6a71646c and 8d04b0c7f56dc46652faa49db5e42b5e8c3a1054.

External image Files selected for processing: 3
  • packages/source-control-github/src/server/GitHubPullRequestApi.test.ts
  • packages/source-control-github/src/server/GitHubPullRequestApi.ts
  • packages/source-control-github/src/server/gitHubGraphQlClient.ts
External image Files with no reviewable changes: 1
  • packages/source-control-github/src/server/gitHubGraphQlClient.ts

Limit details: You’ve used all 10 included reviews currently available.

Walkthrough

The GitHub GraphQL client now classifies NOT_FOUND errors by response path and includes paths in error descriptions. Pull-request detail and action-state reads decode available data when the base-ref comparison is missing.

Changes: Pull-request missing-ref handling

Layer / File(s)Summary
Path-aware GraphQL error reporting
packages/source-control-github/src/server/gitHubGraphQlClient.ts, packages/source-control-github/src/server/GitHubRequestPolicy.ts, packages/source-control-github/src/server/GitHubPullRequestApi.ts, packages/source-control-github/src/server/gitHubGraphQlClient.test.ts, packages/source-control-github/src/server/GitHubPullRequestApi.test.ts
The GraphQL client classifies NOT_FOUND errors by path and includes paths in formatted error descriptions. GitHubApiNotFoundError accepts GitHub error messages. Tests cover path-based classification and error formatting.
Missing-ref read recovery
packages/source-control-github/src/server/GitHubPullRequestApi.ts, packages/source-control-github/src/server/GitHubPullRequestApi.test.ts
Pull-request detail and action-state reads decode response data when the base-ref comparison is missing. The reviewer-refusal fallback accepts that error. Tests cover detail reads, retries, merge and update-branch actions, and errors that remain failures.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Suggested reviewers: juliusmarminge, maria-rcks, t3dotgg

Merge Risk: External image Minimal · up to 8d04b

Pull requests with a missing comparison can remain visible while update-branch stays unavailable. No merge-blocking risk was established.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the main fix: GitHub pull requests with missing head refs no longer appear as not found.
Description checkPassedThe description covers the problem, reproduction, implementation, scope rationale, verification results, and unverified scenarios. It omits the exact “Scope and approval” heading, but it explains why …
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description covers the problem, reproduction, implementation, scope rationale, verification results, and unverified scenarios. It omits the exact “Scope and approval” heading, but it explains why the focused bug fix does not require a prior issue or approval.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Usage-based review receipt

Note

This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

partial verification at exact head afba1efc88adbc62b7fdd4de76617b5e8d5a8973, linux, chrome, real github credentials, and real codex gpt-6.1-sol through the local proxy. no mocks, fixtures, or demo data. no code changes or pushes.

  • installed and ran github/main (32ecd71726) in /home/user/main, then stopped its captured process group before running the pr with isolated /home/user/t3code/.t3 state. only one dev server ran at a time.
  • added projects for real git repositories through the app. submitted real codex turns on main and the pr. both returned the requested github link. on the pr, clicking the provider response opened #25947 inside the app; summary and the five-file code view loaded.
  • opened nonexistent #99999999 through the same client. both versions showed the expected not-found panel. on the pr, the actual websocket response preserved github's message and field path, confirming the changed diagnostic through the github provider, server, and client.

short runtime transcript captured from the actual client websocket:

text
1Request tag=pullRequests.detail
2 host=github.com repository=pingdotgg/t3code number=99999999
3Exit Failure PullRequestOperationError operation=detail reason=not-found
4 GitHub could not find the requested resource, or the credential cannot see it.
5 GitHub said: Could not resolve to a PullRequest with the number of 99999999.
6 (at repository.pullRequest)

raw runtime transcript

blacksmith passed 124 focused tests in GitHubPullRequestApi.test.ts and gitHubGraphQlClient.test.ts. vp run check:changed HEAD^ passed format, lint, graphql generation, knip, typechecks for 11 packages, and both test files. the worker needed the contributor head fetched with depth 2 because its initial snapshot lacked parent history. hosted pr status reported 10 successful checks, none pending or failing.

this clip shows the normal path, not missing-ref recovery. uploaded playback and seeking were checked.

real codex response opens the github pr summary and code view

pr head loads github pr details beside the real codex response

matching neighboring case on main and the pr: a genuinely nonexistent pr stays not found.

main shows the genuine missing-pr error

pr head preserves the genuine missing-pr error

Not verified

the central missing-head-ref recovery remains unverified against live github. the report anonymizes its affected private repository and pr. #25947 itself has a working refs/pull/25947/head comparison. a read-only search of 600 accessible t3code prs found no NOT_FOUND at repository.pullRequest.baseRef.compare; every pr with a base ref had a working comparison. the original bug could not be reproduced on main and its recovery could not be exercised on the pr without inventing a response, which this verification forbids.

also unverified: watch recovery for that missing-ref case, the combined refused-reviewer retry, merge/update-branch mutations, github enterprise, native desktop/mobile, windows/macOS, and remote/relay/tunnel connections. no merge or update-branch mutation was attempted. no labels, branches, or other prs were changed.

this is not a full verification sign-off. completing it requires access to an affected real pr. the only published change is this verification comment.

Added 1 commit

  • chore: merge main into missing pull ref fix59737e8

Note

Written by gpt-6.1-sol on behalf of Maria

merged current github/main (30084f0018c5) into the existing contributor head without rebasing. resolved the graphql client conflict by preserving this pr's messages and field paths alongside main's error-type metadata. the diff against main remains five files, 233 additions and 27 deletions.

blacksmith vp run check:changed 30084f0018c5751a07291222e8d04e16d513700a passed format, lint, knip, graphql generation, 11 package typechecks, and 129 tests. two independent read-only reviews approved 8d04b0c7f56dc46652faa49db5e42b5e8c3a1054 without findings. pushed to the original contributor branch without force.

live recovery against a genuinely missing github pull ref remains unverified, as recorded in the existing verification comment. no new ui behavior was introduced by this merge resolution.

Added 1 commit

  • chore: merge main into missing pull ref fix8d04b0c