Repository navigation
Description
What happened
In a Forgejo project whose origin is an SSH remote on a different hostname from the web UI, "Write review guide" on a linked PR fails with:
Guides are written from this project's checkout, and this pull request is in another repository. Write it from a project that is a checkout of that repository.
The PR is in the project's own repository. It was linked to the thread automatically and shows as open.
This setup is common for self-hosted Forgejo. The web UI sits behind a reverse proxy or tunnel (Caddy, Traefik, nginx, Cloudflare Tunnel) under a public name like git.example.com, and those usually forward only HTTP(S). Git over SSH can't go through them, so it connects straight to the machine running Forgejo by its LAN, VPN or Tailscale name (e.g. git-ssh.internal), often on a non-default port such as 222 because the host's own sshd already uses 22. Some users also use an alias from ~/.ssh/config as the remote host (e.g. forgejo:owner/repo.git). Either way, the remote URL's host never matches the web host, though both point at the same repository.
Diagnosis
The project's identity comes from its SSH remote, for example ssh://[email protected]:222/owner/repo.git. That gives canonicalKey = git-ssh.internal/owner/repo, while webUrl = https://git.example.com/owner/repo. The PR is stored under the web host, git.example.com.
- PR linking works because
isChangeRequestOnProjectHost/isChangeRequestInProjectRepositoryalso accept the project's web URL. requireOwnRepositoryinapps/server/src/pullRequest/PullRequestReviewGuideService.tsbuilds the project's own key withpullRequestSyncKey. That callssourceControlDefinitions.changeRequestHost. For a non-HTTP remote, Forgejo'schangeRequestHost(packages/source-control-forgejo/src/shared/definition.ts) falls back toprojectChangeRequestHost, which is the first part ofcanonicalKey(git-ssh.internal).- So
own.host !== key.host(git-ssh.internalvsgit.example.com), and the guide is rejected.
The same check is unchanged on main. A likely fix: when the identity has a webUrl, Forgejo's changeRequestHost should use that URL's host. Alternatively, requireOwnRepository could match the same way PR linking does. Other code that uses pullRequestSyncKey for SSH-remote Forgejo projects may have the same mismatch.
Steps to reproduce
- Self-hosted Forgejo whose SSH hostname differs from its web hostname (e.g. SSH
git-ssh.internal:222, webgit.example.com). - Add a project whose
originisssh://[email protected]:222/owner/repo.git. T3 resolveswebUrltohttps://git.example.com/owner/repo. - In a thread on that project, open a PR on that repo. It gets linked to the thread as
git.example.com/owner/repo#N. - Click "Write review guide" on that PR.
- The error above appears.
Version
0.1.7-nightly.20261102.4066 (desktop app and its local server). The check is identical on main as of 2026-11-03.
Environment
Linux x64 (CachyOS, kernel 7.3), Node v26.12.1, T3 Code Desktop with a local server. Self-hosted Forgejo reached over SSH through a different hostname than its web UI.
Evidence
- Project `repositoryIdentity`: `canonicalKey: "<ssh-host>/owner/repo"`, `locator.remoteUrl: "ssh://git@<ssh-host>:222/owner/repo.git"`, `webUrl: "https://<web-host>/owner/repo"`, `provider: "forgejo"`
- Thread PR link: `host: "<web-host>"`, `repository: "owner/repo"`, `state: "open"`
- Error toast: "Could not start a review guide — Guides are written from this project's checkout, and this pull request is in another repository. Write it from a project that is a checkout of that repository."Related issues
None found.
Fix applied or workaround
None applied. A possible workaround, not tested: set origin's fetch URL to the HTTPS web URL and keep SSH as the push URL (git remote set-url --push). This needs HTTPS credentials for fetching when the repo is private.
Filed by
Claude Code (Opus 5.5, claude-opus-5-5) via T3 Code triage
Activity
test(server): keep #29753 regression at the Forgejo host layer