can1357/oh-my-pi · error · ToolError
Could not determine a clone URL for ${headRepository}.
Error message
Could not determine a clone URL for ${headRepository}. What it means
When checking out a cross-repository PR, the tool queries `gh repo view` for the head repository's clone URLs and picks one via selectPrCloneUrl (preferring HTTPS or SSH based on your origin's scheme). If both `url` and `sshUrl` come back empty from the GitHub CLI, no clone URL can be constructed, so the tool throws this ToolError instead of adding a broken remote.
Source
Thrown at packages/coding-agent/src/tools/gh-pr-checkout.ts:175
return {
name: "origin",
url: originUrl,
};
}
const headRepository = requireNonEmpty(data.headRepository?.nameWithOwner, "head repository");
const pullRepo = parsePullRequestUrl(data.url).repo;
const pullHost = pullRepo ? parseRepoRef(pullRepo).host : undefined;
const repoSummary = await github.json<GhRepoViewData>(
repoRoot,
["repo", "view", formatRepoRef(pullHost, headRepository), "--json", GH_REPO_CLONE_FIELDS.join(",")],
signal,
{ repoProvided: true },
);
const originUrl = await repository.remoteUrl("origin", signal);
const remoteUrl = selectPrCloneUrl(originUrl ?? undefined, repoSummary);
if (!remoteUrl) {
throw new ToolError(`Could not determine a clone URL for ${headRepository}.`);
}
const remotes = new Map<string, string>();
for (const remoteName of await repository.remoteList(signal)) {
const url = await repository.remoteUrl(remoteName, signal);
if (url) remotes.set(remoteName, url);
}
for (const [remoteName, url] of remotes) {
if (url === remoteUrl) {
return { name: remoteName, url };
}
}
const preferredRemoteName = sanitizeRemoteName(
data.headRepositoryOwner?.login ?? headRepository.split("/")[0] ?? "fork",
);
let remoteName = preferredRemoteName;
let suffix = 2;View on GitHub (pinned to 9690622007)
Solutions
- Verify the head repository still exists and is visible: `gh repo view <owner>/<name> --json url,sshUrl` — if it errors or returns empty fields, the PR head is gone and only the PR author can restore the fork (or you must fetch the PR refs directly).
- Run `gh auth status` and re-authenticate with `gh auth login` (ensure repo scope) so the API returns full repository data.
- As a fallback, fetch the PR ref directly: `git fetch origin pull/<N>/head:pr-<N>` and work from that branch instead of the fork remote.
- Retry later if GitHub had a transient API failure (check githubstatus.com).
Example fix
// manual fallback when tool throws // before: op pr_checkout 1234 → ToolError: Could not determine a clone URL for contributor/fork // after: git fetch origin pull/1234/head:pr-1234 git worktree add ../pr-1234-worktree pr-1234
Defensive patterns
Strategy: fallback
Validate before calling
const view = await github.json<GhRepoViewData>(cwd, ["repo","view",headRepo,"--json","url,sshUrl"], signal);
if (!view.url && !view.sshUrl) throw new Error("head repo clone URLs unavailable — check fork exists and gh auth"); Type guard
function hasCloneUrl(r: { url?: string|null; sshUrl?: string|null }): r is { url: string; sshUrl?: string|null } {
return Boolean(r.url || r.sshUrl);
} Try / catch
try {
await op.prCheckout({ prRef });
} catch (err) {
if (err instanceof ToolError && err.message.includes("Could not determine a clone URL")) {
await git.fetch(["origin", `pull/${prNumber}/head:pr-${prNumber}`]); // fallback to PR ref fetch
} else throw err;
} Prevention
- Confirm the fork still exists (`gh repo view owner/fork`) before checking out old PRs.
- Keep gh authenticated with repo scope: run `gh auth status` in CI setup.
- For private-fork PRs, ensure your token has access to the fork's org.
- Have a standing fallback: fetch `pull/N/head` refs directly.
When it happens
Trigger: Calling op pr_checkout for a PR from a fork/head repository where `gh repo view <headRepository> --json url,sshUrl` returns null/empty for both url and sshUrl — e.g. the fork was deleted after the PR was opened, the authenticated token cannot see the head repo (private fork of an org repo), or a GitHub API outage/gh CLI version quirk drops the fields.
Common situations: Contributor deleted their fork after opening a PR; PR from a private fork the local token lacks access to; enterprise/hosted GitHub instances where gh returns partial repo JSON; stale gh auth (gh auth login not run or expired scope) causing empty repo view output.
Related errors
- timed out: {command}
- Failed to refresh Bun's git cache for ${source.host}/${sourc
- Cloned repository ${url}: ${(err as Error).message} (source:
- GitHub CLI did not return a pull request number.
- git timed out after {effective_timeout:.0f}s: {' '.join(_red
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b60a4cdd598b42e2.
Report an issue: GitHub.