Repository navigation
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
- Use two GitHub accounts, each able to see a different set of private repositories. Account A sees
org-a/*; account B seesorg-b/*. Neither can see the other's repositories. - Select the account per repository with a small
ghwrapper onPATHthat setsGH_CONFIG_DIRfrom the working directory. Each account has its own config directory, soghrun from anorg-acheckout authenticates as A, and from anorg-bcheckout as B. - Open projects for repositories from both orgs, with threads that have linked pull requests.
Expected behavior
Pull request lookups for a thread run in that thread's workspace, the way they did in 0.0.43-nightly.20260925.2269. Each lookup then authenticates as the account that can see the repository, and pull request status and the pull request pane load for every project.
Actual behavior
In 0.0.43-nightly.20260928.2375, pull request sync runs every project's lookups from one working directory. It appears to be the first project's workspace, unrelated to the thread. I sampled the spawned processes:
gh pr view <n> --repo github.com/org-b/<repo> --json ...runs from theorg-aproject's directory, so it authenticates as A and fails withCould not resolve to a Repository.gh api graphqlwith aPullRequestSummariesquery batches repositories from both orgs into one query (s0: repository(owner: "org-b", ...),s1: repository(owner: "org-a", ...)). No single account can answer that query. Under either account, GitHub returns partialdataplus aNOT_FOUNDerror, andghexits 1.
The server logs pull request sync skipped for every pull request in the other org each minute, and the pull request pane shows "Could not load pull requests. Pull request operation detail failed: GitHub CLI command failed."
Impact
Anyone who separates GitHub accounts per client or organization (for example with GH_CONFIG_DIR per directory, or with gh configured differently per checkout) loses pull request status and the pull request pane for every repository the directory T3 picked can't see. The only workarounds are giving one account access to every org, which defeats the separation, or routing the account from the command's arguments instead of the working directory.
Version or commit
Regressed between 0.0.43-nightly.20260925.2269 (works) and 0.0.43-nightly.20260928.2375 (fails). Possibly related to the pull request sync changes in #13704 or #13691, but I haven't bisected.
Environment
Linux x64, server run as a systemd user service, gh 2.x.
Logs or stack traces
[17:43:25.899] WARN (#513610): pull request sync skipped
{ key: 'github.com/org-b/repo-x#15' }
A mixed-owner query reproduces the partial failure directly under either account:
$ gh api graphql -f query='query { s0: repository(owner: "org-b", name: "repo-x") { pullRequest(number: 15) { state } } s1: repository(owner: "org-a", name: "repo-y") { pullRequest(number: 41) { state } } }'
{"data":{"s0":null,"s1":{"pullRequest":{"state":"OPEN"}}},"errors":[{"type":"NOT_FOUND","path":["s0"],...}]}
gh: Could not resolve to a Repository with the name 'org-b/repo-x'.
exit status 1
Workaround
Route the account from the repository named in the command (--repo, repos/<owner>/..., GraphQL owner:) rather than the working directory. That restores the per-pull-request lookups. A mixed-owner batched query still fails for one side.
Suggested fix: run lookups from each thread's workspace as before, or batch GraphQL queries per workspace or per credential rather than across all projects.
Activity
juliusmarminge commentedon Sep 28, 2026
Triage
Confirmed on current
main(d15210cd, which isv0.0.43-nightly.20260928.2375). The mixed-ownerPullRequestSummariesquery is what this sync does. Not a duplicate of #14113: that failure is an interrupt on first open (All fibers interrupted without error). This one isghexiting 1.Background sync asks for every due link together (
PullRequestSyncReactor, concurrency 25). Eachsummarybecomes aPullRequestSummaryRead, and those reads are grouped only by host and pinned credential:Sync never pins a credential, so every
github.comlink that arrives in the 10ms window shares one group. The query runs inentries[0]'s working directory, which is whichever request got there first, not the thread that owns the repository.ghexits 1 when any aliased repository is invisible to that directory's account, the whole document is dropped, and the sweep logspull request sync skippedwith only the key.A failed document is then supposed to fall back to one
gh pr viewper entry, using that entry's owncwd.summarysets thatcwdfrom the projectrequireProjectreturns. When the link's repository matches the thread's project, that is the thread's checkout.repositoryArgsalways passes--repo <host>/<owner>/<name>, so--repo github.com/org-b/...does not by itself mean the target was rewritten.A
gh pr viewfor org-b whose process cwd is an org-a checkout means the serving project was not org-b. That is the host fallback inrequireProject: a GitHub ref may be answered by any checkout on the host, and the last resort is the first non-Azure checkout, with the requested repository written onto it. The pull-request list (readTogether) andlistStatsdo the same thing on purpose (cwdischunk[0]'s workspace; the search API comment says "any checkout on the host"). Detail is not in the summary batch.Pull request operation detail failed: GitHub CLI command failedis that read's ownghfailing in whichever checkoutrequireProjectselected, which is also what the pane renders.This resolver is unchanged between
v0.0.43-nightly.20260925.2269and2375. It landed in #13198 (2026-09-22), which is already in 2269. #13704 only stops the sweep from loading threads that have no links. #13691 changes which threads settlement reads, not which directoryghruns in. If 2269 really did run each lookup in the thread checkout, the difference is whether those reads landed in one 10ms batch. The code that collapses them was already there.Group summary batches by the credential
gh auth tokenreturns in that request's cwd (the fingerprintcaptureVerifiedCredentialalready computes), and run each query from a cwd that produced it. Do the same for the list and stat reads that take the first workspace in the chunk. A mixed-owner document cannot be split afterghhas already failed it.fix(source-control): each repository is read with the GitHub account …
fix(source-control): each repository is read with the GitHub account …
Chinoman10 commentedon Oct 18, 2026
I reproduced a related case with two organisation-scoped PATs belonging to the same GitHub login: Git HTTPS access works, but T3's saved host token cannot resolve the other organisation's private repository before cloning. #21264 records that reproduction.
#21265 adds an explicitly enabled server option that reuses existing global Git HTTPS helpers and separates native GraphQL summary/watch batches by selected credential and repository. It also keeps operation pins and caches separate when the tokens have the same viewer. This provides a Git-helper route for the mixed-credential boundary described here; it preserves the existing default and does not change per-checkout
ghwrapper behavior. The PR includes focused tests and native remote import/PR-read evidence.1nto5 commentedon Oct 19, 2026
+1, still happening on 0.1.1-nightly. Setup: three accounts on github.com (a personal default plus two work accounts for different owners) and one self-hosted GitLab. A
ghwrapper earlier onPATHpicks the account from the repo owner (-R, then theoriginremote). Terminal and git work per repo, but T3 uses one GitHub token per host for every project, so the mobile Pulls tab shows<owner>/<repo> could not be readfor the other two owners.What would fix it: pick the credential per project or per owner (for example an account picker per project in Settings → Source Control), or resolve it in each project's checkout as before the API transport. Ideally the same for GitLab and other forges.
KristijanJovanovski commentedon Oct 29, 2026
Still happening on
0.1.4-nightly.20261028.3824(macOS), and it affects T3's own GitHub sign-in, not onlyghwrapper setups.Setup: two GitHub accounts on the same machine, each able to see private repositories the other cannot. Selecting the account in one project's Source Control settings changes it for every project, so it behaves as a single global setting and it is always one account or the other.
Projects whose repositories belong to the other account then fail every PR sync with
GitHubApiNotFoundError: GitHub could not find the requested resource, or the credential cannot see it(mostGitHubPullRequestApi.getPullRequestSummaryspans inserver.trace.ndjsonexit with this), andwatch_pull_requestdrops after 8 failed reads.ghauthenticated as the right account reads the same PR without issue.+1 for selecting the credential per project (or per repository owner).
jcardama commentedon Oct 30, 2026
Still happens on
0.1.6-nightly.20261030.3904(Linux x64, server as a systemd user service). The setup is the same as above: account A seesorg-a/*, account B seesorg-b/*, and aghwrapper onPATHselects the account.Observed:
pull request sync skipped28 times. All 28 entries are for linked pull requests inorg-brepositories. Each entry has this reason:Pull request operation summary failed: GitHub could not find the requested resource, or the credential cannot see it.org-arepositories give no errors.Cause, from the
0.1.6bundle (GitHubCredentials):gh auth token --hostname github.com. This command names no repository.process.cwd(), here the home directory), not in the project's checkout. Thus a wrapper that selects the account from the working directory or from--repoalways returns account A.hosts[host].account) is also per host. No setting selects a different account for one owner or repository.#21581 and #21582 (select the account by owner and repository) appear to fix this.
bigintersmind commentedon Nov 12, 2026
Still happening on 0.1.8 (T3 Code Desktop, macOS arm64). The server runs on an always-on Mac, and I connect to it from the desktop app on another Mac. Which client I use makes no difference, because the reads happen on the server. v0.1.9 doesn't fix it either:
GitHubCredentialshasn't changed, and #21581, #21582 and #21265 are still open.Setup: two github.com accounts. A is the default
ghlogin. B lives in its ownGH_CONFIG_DIRand is the only one that can see theorg-b/*repos. direnv picks the account per directory, and aghwrapper earlier onPATHpicks it per repo owner (from--repo, thenrepos/<owner>/…, then theoriginremote). Git uses a per-URL credential helper pointed at B's config. Git,ghin a terminal, and the agents' ownghcalls all use the right account.What T3 does:
GitHubCredentialsrunsgh auth token --hostname github.comfrom the server's working directory without naming a repository. The wrapper has nothing to route on, so it returns A, and T3 caches that one token for every github.com repo. Every read of anorg-bPR then fails withGitHubApiNotFoundError(credential: "gh", ingetPullRequestDetailandgetPullRequestSummary).Impact on this install:
server.trace.ndjsonshow 3,377 failedPullRequestSyncReactor.syncGroupspans, each withPull request operation summary failed: GitHub could not find the requested resource, or the credential cannot see it.Every PR the failures name is in anorg-brepo.watch_pull_requesthas given up 79 times across 13 threads ("stopped watching … because it failed to read it from the host 8 times in a row"). All 79 watches were on PRs in twoorg-brepos.Not covered in this thread yet: agents can't fall back to their own
gh. The instructions T3 adds for agents (<pull_request_linking>) tell them to usewatch_pull_requestand forbidgh --watch, loops, sleep, Monitor and ScheduleWakeup for PR waits. That holds even when T3's credential can't see the repo. The agent callswatch_pull_request, the watch fails 8 reads and stops, and the agent is then told to check by hand. Its own shell has aghthat works for these repos, but it isn't allowed to wait with it. Until per-owner or per-repo accounts land, either of these would help:gh.My workaround for now is a user-level instruction: for
org-bPRs, don't callwatch_pull_request; rungh pr checks <n> --repo … --watchin the background instead.+1 for #21582 (choosing the account by owner and repository). The opt-in in #21265, which reuses existing git credential helpers, would also fix this setup without extra configuration, since the git helper already sends
org-bto account B.Investigated and written by Claude Opus 5.5 (Claude Code harness, T3 Code triage session).
juliusmarminge commentedon Nov 12, 2026
Thanks for writing this up. It asks for new behaviour rather than reporting a defect, so it does not belong in the bug tracker and I'm closing it as not planned here. Feature ideas are discussed in Discussions: please post it there.