can1357/oh-my-pi · error · ToolError

local branch ${localBranch} does not exist

Error message

local branch ${localBranch} does not exist

What it means

executePrPush resolves the branch to push: either the `branch` parameter or the current branch. It then verifies that branch actually exists locally via refExists; if not, there is nothing to push and it throws. Note this checks a real local branch — a detached HEAD or a typo'd name both land here.

Source

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

		branch: outcome.localBranch,
		worktreePath: outcome.worktreePath,
		remote: outcome.remoteName,
		remoteBranch: outcome.headRefName,
		reused: outcome.reused,
	};
}

export async function executePrPush(
	session: ToolSession,
	params: GithubInput,
	signal: AbortSignal | undefined,
): Promise<AgentToolResult<GhToolDetails>> {
	const repoRoot = await requireGitRepoRoot(session.cwd, signal);
	const repository = vcs.requireGit(repoRoot);
	const localBranch = normalizeOptionalString(params.branch) ?? (await requireCurrentGitBranch(repoRoot, signal));
	const refExists = await repository.refExists(toLocalBranchRef(localBranch), signal);
	if (!refExists) {
		throw new ToolError(`local branch ${localBranch} does not exist`);
	}

	const target = await resolvePrBranchPushTarget(repoRoot, localBranch, signal);
	const currentBranch = await repository.currentBranch(signal);
	const sourceRef = currentBranch === localBranch ? "HEAD" : toLocalBranchRef(localBranch);
	const refspec = `${sourceRef}:refs/heads/${target.remoteBranch}`;
	await repository.push(
		{
			forceWithLease: params.forceWithLease,
			refspec,
			remote: target.remoteName,
		},
		signal,
	);

	// A successful push changes what `pr://N` and `pr://N/diff` should show;
	// drop the cached rows so the canonical "push → re-read diff" flow sees
	// fresh data instead of a soft-TTL stale snapshot.

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the exact name with `git branch --list <name>`; fix the typo in the branch parameter if it is misspelled.
  2. Create or restore the branch: `git switch -c <branch>` (or `git switch <branch>` if it exists elsewhere), then re-run the push.
  3. If HEAD is detached, create a branch at HEAD first (`git switch -c <branch>`) so a real local ref exists to push.
  4. Verify you are in the right repository/worktree — the branch may exist in another worktree or clone.

Example fix

// before
op pr_push --branch fix-typo   // branch never created
// after
git switch -c fix-typo
op pr_push --branch fix-typo
Defensive patterns

Strategy: validation

Validate before calling

const branch = params.branch ?? await repo.currentBranch();
if (!branch || !(await repo.refExists(`refs/heads/${branch}`))) {
  throw new Error(`local branch ${branch} does not exist — create it before pr_push`);
}

Try / catch

try {
  await op.prPush({ branch });
} catch (err) {
  if (err instanceof ToolError && err.message.includes("does not exist")) {
    await git.switch(["-c", branch]); // create at HEAD, then retry
    await op.prPush({ branch });
  } else throw err;
}

Prevention

When it happens

Trigger: Running the pr_push op with `branch` set to a non-existent name; running on a detached HEAD where requireCurrentGitBranch / branch resolution yields a name with no local ref; branch was deleted locally but PR metadata still references it; typo in the branch parameter.

Common situations: Typo in --branch; after `git branch -D` cleanup the push op is retried; worktree/CI context where the branch was never created locally; detached HEAD during a rebase or bare-commit checkout.

Related errors


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