{"record":{"id":"e9883201201ee7ff","repo":"can1357/oh-my-pi","slug":"invalid-pr-identifier-prref-pass-a-pr-number","errorCode":null,"errorMessage":"invalid PR identifier: ${prRef}. Pass a PR number, URL, or branch name.","messagePattern":"invalid PR identifier: (.+?)\\. Pass a PR number, URL, or branch name\\.","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/gh-pr-checkout.ts","lineNumber":398,"sourceCode":"\nexport interface PrCheckoutOutcome {\n\tdata: GhPrViewData;\n\tlocalBranch: string;\n\tworktreePath: string;\n\tremoteName: string;\n\tremoteUrl: string;\n\theadRefName: string;\n\treused: boolean;\n}\n\nexport async function checkoutPullRequest(\n\tsession: ToolSession,\n\tsignal: AbortSignal | undefined,\n\toptions: PrCheckoutOptions,\n): Promise<PrCheckoutOutcome> {\n\tconst { prRef, repo, force } = options;\n\tif (prRef?.startsWith(\"-\")) {\n\t\tthrow new ToolError(`invalid PR identifier: ${prRef}. Pass a PR number, URL, or branch name.`);\n\t}\n\tconst args = [\"pr\", \"view\"];\n\tif (prRef) args.push(prRef);\n\tappendRepoFlag(args, repo, prRef);\n\targs.push(\"--json\", GH_PR_CHECKOUT_FIELDS.join(\",\"));\n\n\tconst data = await github.json<GhPrViewData>(session.cwd, args, signal, {\n\t\trepoProvided: Boolean(repo),\n\t});\n\tconst prNumber = data.number;\n\tif (typeof prNumber !== \"number\") {\n\t\tthrow new ToolError(\"GitHub CLI did not return a pull request number.\");\n\t}\n\n\tconst headRefName = requireNonEmpty(data.headRefName, \"head branch\");\n\tconst headRefOid = requireNonEmpty(data.headRefOid, \"head commit\");\n\tconst repoRoot = await requireGitRepoRoot(session.cwd, signal);\n\tconst primaryRepoRoot = await requirePrimaryGitRepoRoot(repoRoot, signal);","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/gh-pr-checkout.ts#L380-L416","documentation":"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.","triggerScenarios":"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.","commonSituations":"Copy-pasting CLI flags into the identifier field; negative numbers from miscalculated templates; scripting that joins flags and identifiers into one argument.","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."],"exampleFix":"// before\nop pr_checkout --pr-ref \"--repo owner/name\"\n// after\nop pr_checkout --pr-ref 1234 --repo owner/name","handlingStrategy":"validation","validationCode":"function isValidPrRef(ref) {\n  return typeof ref === \"string\" && ref.length > 0 && !ref.startsWith(\"-\") &&\n    (/^\\d+$/.test(ref) || /^https:\\/\\/github\\.com\\//.test(ref) || /^[A-Za-z0-9._\\/-]+$/.test(ref));\n}\nif (!isValidPrRef(prRef)) throw new Error(`invalid PR identifier: ${prRef}`);","typeGuard":"function isPrRef(v: unknown): v is string {\n  return typeof v === \"string\" && v.length > 0 && !v.startsWith(\"-\");\n}","tryCatchPattern":"try {\n  await op.prCheckout({ prRef });\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes(\"invalid PR identifier\")) {\n    throw new UserInputError(\"Pass a PR number, URL, or branch name — flags go in the repo option\");\n  } else throw err;\n}","preventionTips":["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)."],"tags":["input-validation","argument-injection","pr-checkout"],"backgroundTag":"invalid-argument","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}