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
- 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.
- 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).
- 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
- Never concatenate CLI flags into the prRef field.
- Validate identifiers against /^\d+$/ or a PR URL pattern before calling.
- Pass repository scope via the separate repo parameter.
- Sanitize script-generated identifiers (strip stray dashes/whitespace).
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
- err.to_string() (timestamp parse error)
- duration is too large: {value}
- invalid date: {value}
- date is out of range
- dates before 1970 are unsupported
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e9883201201ee7ff.
Report an issue: GitHub.