Repository navigation
[Bug]: PR views fail with a fine-grained GitHub token (check runs are unreadable) #15229
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Create a fine-grained personal access token for a repository that runs GitHub Actions on pull requests. Give it read (or higher) on Pull requests, Contents, Issues, Actions, Workflows, Commit statuses, and Metadata.
- On the machine running the T3 Code server:
gh auth login --with-token < token.txt - Open a project for that repository in T3 Code, and open the pull request list or any pull request.
Expected behavior
Pull requests load. A token that can't read checks should still let T3 Code show the pull request without them.
Actual behavior
The pull request list and pull request detail fail completely. Plain gh commands with the same token work, for example gh pr checkout and gh pr list without check fields.
The pull request list and detail ask for check status in the same request as everything else:
- The list uses
gh pr list --json …,statusCheckRollup(PULL_REQUEST_LIST_JSON_FIELDSinapps/server/src/pullRequest/gitHubPullRequestJson.ts). - The detail uses
pullRequestCoreGraphQlQuery, in the same file, which reads every check understatusCheckRollup.contexts.
On a repository that uses GitHub Actions, those checks are check runs. Reading check runs needs the Checks permission, which GitHub grants only to GitHub Apps. A fine-grained personal access token can't be given it. When one field is refused, gh exits non-zero and the whole read fails, so one unreadable optional field takes down the whole pull request view.
Adding Commit statuses: Read gets past the rollup itself, but each check run inside it is still refused. The REST checks endpoint returns 403 with the same token, so this comes from GitHub's permission model, not from gh.
The error also isn't recognised: classifyNonZeroExit (apps/server/src/vcs/VcsProcess.ts) reports it as a generic command failure, with no hint that the token type is the cause.
Impact
Major degradation or frequent failure
Version or commit
main @ ce90eec
Environment
T3 Code server on Debian, used remotely. gh from the official cli.github.com apt repository (reproduced both before and after upgrading from Debian's packaged gh). github.com.
Logs or stack traces
# Each field requested separately with `gh pr list --json number,<field>`:
PASS pr list --json author / mergeable / reviewDecision / additions / reviewRequests / latestReviews / labels
PASS graphql assignableUsers
# Without Commit statuses:
FAIL pr list --json statusCheckRollup
GraphQL: Resource not accessible by personal access token (repository.pullRequests.nodes.0.statusCheckRollup.nodes.0.commit.statusCheckRollup)
# With Commit statuses: Read added, each check run is still refused:
FAIL pr list --json statusCheckRollup
GraphQL: Resource not accessible by personal access token (repository.pullRequests.nodes.0.statusCheckRollup.nodes.0.commit.statusCheckRollup.contexts.nodes.0), … (one per check run)
FAIL PR detail GraphQL query
gh: Resource not accessible by personal access token
$ gh api repos/OWNER/REPO/commits/SHA/check-runs
{"message":"Resource not accessible by personal access token","documentation_url":"https://docs.github.com/rest/checks/runs#list-check-runs-for-a-git-reference","status":"403"}Workaround
Sign gh in with gh auth login --web, or with a classic personal access token that has the repo scope. Both can read check runs.
Activity
[-][Bug]: PR views and merge auto-settle fail with a fine-grained GitHub token (check runs are unreadable)[/-][+][Bug]: PR views fail with a fine-grained GitHub token (check runs are unreadable)[/+]juliusmarminge commentedon Oct 3, 2026
Note
Grok responding on behalf of Julius.
Triage
Thanks @ClumsyAdmin for the field-by-field breakdown. It made this easy to confirm. I checked it on
mainatce90eec1ff, and no existing issue covers it.A fine-grained personal access token can't read check runs. GitHub doesn't offer a Checks permission for that token type, so
GET /repos/{owner}/{repo}/commits/{sha}/check-runsreturns 403 even when Commit statuses, Actions, and Workflows are readable. A classic token with thereposcope, orgh auth login --web, can read them. That part is GitHub's permission model, and your workaround is right.The T3 Code side is that it asks for those checks in the same
ghcall as the pull request itself.ghexits non-zero when any selected field is refused, and nothing retries without the checks.classifyNonZeroExitinapps/server/src/vcs/VcsProcess.tsdoesn't recognize the message, so it shows up as a generic command failure.Where it fails
PULL_REQUEST_LIST_JSON_FIELDSinapps/server/src/pullRequest/gitHubPullRequestJson.tsincludesstatusCheckRollup, which matches your log: every other field passes, andstatusCheckRollupfails once the head commit has check runs.pullRequestCoreGraphQlQueryin the same file selectsstatusCheckRollup.contextsand eachCheckRun(includingcheckSuite.workflowRun), so one refused check fails the read.pullRequestSearchGraphQlQuery, which asks only forstatusCheckRollup { state }). If that's refused, it falls back togh pr list --jsonwith the full rollup, which fails too, and the repository is reported as unreadable.ThreadSettlementServicereads the linked pull request throughsummarywithrecoverTransientFailure: false. The batched summary asks forstatusCheckRollup { state }, a GraphQL error drops the whole batch, and the per-PR fallbackgh pr view --jsonusesPULL_REQUEST_DETAIL_JSON_FIELDS, which includes every check. Settlement only needsstateandmergedAt, but never gets them, so a merged thread stays unsettled.A repository whose head commit has no check runs isn't affected.
Likely fix area
A maintainer will decide on the fix direction. One option is to treat checks as optional: when they can't be read, the list, detail, and settlement reads still succeed with check state shown as unknown, and the token-type error is recognized so the message points at the cause.
ScottN-PV commentedon Oct 15, 2026
#16171 closed for going over the 500-line limit, so here is a smaller fix to agree on first.
From reading main
42da166d13: the list, pull request page and merge-settlement reads now ask only for the overall check state, so with Commit statuses: Read they no longer need check-run access. Opening a pull request still reads every check run, andGitHubApifails the whole answer on any refusal, so the detail view fails whenever the token cannot read the head's check runs. I have not rerun this SHA with a fine-grained token; #16171's earlier token run saw the same split.Two options:
A. When the detail read is refused only for checks, read it again without them and show checks as unavailable (not "No checks reported") on web and mobile. About 80–200 non-test lines, under 400 with tests.
B. Keep the failure, but add a line to the existing error saying the server's token cannot read check runs. About 20–30 non-test lines.
We prefer A. Would you take A, or B first?
Note
Comment drafted by Claude Fable 5.1 on behalf of @ScottN-PV.
t3dotgg commentedon Oct 21, 2026
Note
🤖 Claude Opus 5.5 responding on behalf of Theo
Thanks for the report. One part of this is fixed on main in #16320 and #19224. Please test on the nightly built from main on 2026-10-21, or on the next stable release. One part is still open: Opening PR detail can still fail when the token cannot read check runs. If that part still matters to you, please open a new issue for that part only.