can1357/oh-my-pi · error · ToolError
local branch ${localBranch} already exists at ${formatShortS
Error message
local branch ${localBranch} already exists at ${formatShortSha(existingOid ?? undefined) ?? existingOid ?? "unknown commit"}; pass force=true to reset it What it means
When checking out a PR, the tool wants to create local branch <localBranch>. If that branch already exists and points at a different commit than the PR head (headRefOid), creating it would either fail or silently diverge, so without force=true the tool throws and tells you the existing commit and how to override.
Source
Thrown at packages/coding-agent/src/tools/gh-pr-checkout.ts:451
const existingWorktree = existingWorktrees.find(entry => entry.branch === toLocalBranchRef(localBranch));
const remote = await ensurePrRemoteWithRepo(repoRoot, data, repository, signal);
await repository.fetch(
remote.name,
`refs/heads/${headRefName}`,
`refs/remotes/${remote.name}/${headRefName}`,
PR_FETCH_TIMEOUT_MS,
signal,
);
if (!existingWorktree) {
const localBranchRef = toLocalBranchRef(localBranch);
const localBranchExists = await repository.refExists(localBranchRef, signal);
if (localBranchExists) {
const existingOid = await repository.resolveRef(localBranchRef, signal);
if (existingOid !== headRefOid) {
if (!force) {
throw new ToolError(
`local branch ${localBranch} already exists at ${formatShortSha(existingOid ?? undefined) ?? existingOid ?? "unknown commit"}; pass force=true to reset it`,
);
}
await repository.createBranch(
localBranch,
`refs/remotes/${remote.name}/${headRefName}`,
true,
signal,
);
}
} else {
await repository.createBranch(localBranch, `refs/remotes/${remote.name}/${headRefName}`, false, signal);
}
}
const configPrefix = `branch.${localBranch}.`;
await repository.configSet(`${configPrefix}remote`, remote.name, signal);View on GitHub (pinned to 9690622007)
Solutions
- Re-run the checkout with force=true (force option) to reset the existing local branch to the PR head commit — but first confirm you have no unpushed local commits on that branch you need.
- If the local branch has your own work, rename it first: `git branch -m <localBranch> <localBranch>-backup`, then check out the PR again.
- Compare the commits before forcing: `git log <localBranch>..HEAD` / check the existing SHA from the message to decide whether resetting loses anything.
Example fix
// before: second checkout of PR 123 after new upstream commits // ToolError: local branch pr/123 already exists at abc1234; pass force=true // after op pr_checkout 1234 force=true // resets pr/123 to new head git branch -m pr/123 pr/123-old // ...or preserve local work first
Defensive patterns
Strategy: validation
Validate before calling
const branchRef = `refs/heads/${localBranch}`;
if (await repo.refExists(branchRef)) {
const oid = await repo.resolveRef(branchRef);
if (oid !== prHeadOid && !hasUnpushedWork(branchRef)) {
// safe to force-reset
}
} Try / catch
try {
await op.prCheckout({ prRef, force: false });
} catch (err) {
if (err instanceof ToolError && err.message.includes("already exists")) {
await git.branch(["-m", localBranch, `${localBranch}-backup`]); // preserve, then retry
await op.prCheckout({ prRef });
} else throw err;
} Prevention
- Before re-checkout, check for unpushed commits on the existing branch.
- Rename or delete stale pr/* branches after merging.
- Avoid creating personal branches named like the tool's PR branches (pr/<N>).
- Only pass force=true after confirming the existing branch holds nothing unique.
When it happens
Trigger: Running op pr_checkout twice for the same PR after the PR gained new commits (local branch still at old head); a pre-existing branch with the same conventional name (e.g. `pr/123` or the head branch name) from another source; a stale checkout from a previous session.
Common situations: Re-checking out an actively updated PR; name collision with a user's own branch; reusing a repo where someone branched locally with the same name.
Related errors
- not a repository: {path}
- reference not found: {name}
- object not found: {spec}
- cherry-pick of {sha} is empty
- merge conflict in {} file(s)
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/4d37b78c035db198.
Report an issue: GitHub.