can1357/oh-my-pi · error · ToolError

invalid PR identifier: ${prRef}. Pass a PR number, URL, or b

Error message

invalid PR identifier: ${prRef}. Pass a PR number, URL, or branch name.

What it means

checkoutPullRequest validates the prRef argument before invoking `gh pr view`; a ref starting with '-' would be interpreted by the gh CLI as a flag rather than an identifier, enabling argument injection. The tool rejects it up front and asks for a PR number, URL, or branch name.

Source

Thrown at packages/coding-agent/src/tools/gh-pr-checkout.ts:398

export interface PrCheckoutOutcome {
	data: GhPrViewData;
	localBranch: string;
	worktreePath: string;
	remoteName: string;
	remoteUrl: string;
	headRefName: string;
	reused: boolean;
}

export async function checkoutPullRequest(
	session: ToolSession,
	signal: AbortSignal | undefined,
	options: PrCheckoutOptions,
): Promise<PrCheckoutOutcome> {
	const { prRef, repo, force } = options;
	if (prRef?.startsWith("-")) {
		throw new ToolError(`invalid PR identifier: ${prRef}. Pass a PR number, URL, or branch name.`);
	}
	const args = ["pr", "view"];
	if (prRef) args.push(prRef);
	appendRepoFlag(args, repo, prRef);
	args.push("--json", GH_PR_CHECKOUT_FIELDS.join(","));

	const data = await github.json<GhPrViewData>(session.cwd, args, signal, {
		repoProvided: Boolean(repo),
	});
	const prNumber = data.number;
	if (typeof prNumber !== "number") {
		throw new ToolError("GitHub CLI did not return a pull request number.");
	}

	const headRefName = requireNonEmpty(data.headRefName, "head branch");
	const headRefOid = requireNonEmpty(data.headRefOid, "head commit");
	const repoRoot = await requireGitRepoRoot(session.cwd, signal);
	const primaryRepoRoot = await requirePrimaryGitRepoRoot(repoRoot, signal);

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass only a PR number (e.g. "1234"), full PR URL (https://github.com/owner/repo/pull/1234), or a branch name — no leading dash.
  2. Strip stray flags from the identifier and pass repo separately via the `repo` parameter (e.g. `--repo owner/name` is the repo option, not part of prRef).
  3. If a negative-looking number comes from a script, coerce it to a string number without the sign or validate the source value.

Example fix

// before
op pr_checkout --pr-ref "--repo owner/name"
// after
op pr_checkout --pr-ref 1234 --repo owner/name
Defensive patterns

Strategy: validation

Validate before calling

function isValidPrRef(ref) {
  return typeof ref === "string" && ref.length > 0 && !ref.startsWith("-") &&
    (/^\d+$/.test(ref) || /^https:\/\/github\.com\//.test(ref) || /^[A-Za-z0-9._\/-]+$/.test(ref));
}
if (!isValidPrRef(prRef)) throw new Error(`invalid PR identifier: ${prRef}`);

Type guard

function isPrRef(v: unknown): v is string {
  return typeof v === "string" && v.length > 0 && !v.startsWith("-");
}

Try / catch

try {
  await op.prCheckout({ prRef });
} catch (err) {
  if (err instanceof ToolError && err.message.includes("invalid PR identifier")) {
    throw new UserInputError("Pass a PR number, URL, or branch name — flags go in the repo option");
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a prRef beginning with a dash — e.g. an accidentally pasted option like `--repo owner/name` as the identifier, a leading hyphen from copy/paste (`-1234`), or a shell-expansion artifact in the pr_checkout/pr_view op parameters.

Common situations: Copy-pasting CLI flags into the identifier field; negative numbers from miscalculated templates; scripting that joins flags and identifiers into one argument.

Related errors


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