can1357/oh-my-pi · error · ToolError

run URL repository does not match the provided repo

Error message

run URL repository does not match the provided repo

What it means

resolveGitHubRepo cross-checks a caller-supplied repo against a repo parsed from a run URL; if both are present and the slugs differ (case-insensitive compare via githubRepoSlugEquals), it throws this ToolError. It prevents acting on a run belonging to a different repository than requested.

Source

Thrown at packages/coding-agent/src/tools/gh-common.ts:238

 * the host `gh` itself resolved from the remote.
 */
async function resolveRepoFromCwd(cwd: string, signal?: AbortSignal): Promise<string> {
	const url = requireNonEmpty(await github.text(cwd, ["repo", "view", "--json", "url", "-q", ".url"], signal), "repo");
	const repo = repoFromUrl(url);
	if (!repo) {
		throw new ToolError(`GitHub CLI returned an unrecognized repository URL: ${url}`);
	}
	return repo;
}

export async function resolveGitHubRepo(
	cwd: string,
	repo: string | undefined,
	runRepo: string | undefined,
	signal?: AbortSignal,
): Promise<string> {
	if (repo && runRepo && !githubRepoSlugEquals(repo, runRepo)) {
		throw new ToolError("run URL repository does not match the provided repo");
	}

	if (repo) {
		return repo;
	}

	if (runRepo) {
		return runRepo;
	}

	return resolveRepoFromCwd(cwd, signal);
}

/**
 * Process-lifetime cache of `gh repo view` lookups keyed by absolute cwd.
 * Avoids repeated `gh` chatter when the same protocol handler or tool call
 * resolves the default repo many times in a row.
 *

View on GitHub (pinned to 9690622007)

Solutions

  1. Make the repo parameter match the repository in the run URL, or drop the explicit repo so it is inferred from the URL.
  2. Verify the run URL belongs to the intended repository (compare owner/name in the link).
  3. If working across forks, use the repo slug where the run actually exists.

Example fix

// before
await resolveGitHubRepo(cwd, "acme/api", "https://github.com/acme/api-fork/actions/runs/9");
// after
await resolveGitHubRepo(cwd, "acme/api-fork", "https://github.com/acme/api-fork/actions/runs/9");
Defensive patterns

Strategy: validation

Validate before calling

function repoSlugFromRunUrl(url) {
  const m = url.match(/^https:\/\/[^/]+\/([^/]+\/[^/]+)\//);
  return m ? m[1] : null;
}
const slug = repoSlugFromRunUrl(runUrl);
if (repo && slug && repo.replace(/\.git$/, "").toLowerCase() !== slug.toLowerCase()) {
  throw new Error("repo does not match run URL");
}

Try / catch

try {
  await resolveGitHubRepo(cwd, repo, runUrl);
} catch (err) {
  if (err instanceof ToolError && err.message.includes("does not match the provided repo")) {
    // derive repo from the run URL instead
    repo = repoSlugFromRunUrl(runUrl);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling resolveGitHubRepo (via tryResolveCurrentRepoFresh or repo accessor) with repo="owner/a" while the run URL points at owner/b — e.g. a copied run URL from another repo combined with an explicit repo flag.

Common situations: Prompt supplies a run URL from a different repository than the agent's cwd repo; user typo in the repo slug or pasted the wrong workflow run link; fork where the run lives under the fork's slug but user passes upstream.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/91724ec6ab19c0d1. Report an issue: GitHub.