can1357/oh-my-pi · error · ToolError

Current git branch is unavailable. Pass `branch` or `run` ex

Error message

Current git branch is unavailable. Pass `branch` or `run` explicitly.

What it means

requireCurrentGitBranch asks the local git repo for the current branch and throws this ToolError when neither a repo nor a branch can be determined. It exists so gh tools fail with a clear message telling the caller to supply `branch` (or `run`) explicitly instead of guessing.

Source

Thrown at packages/coding-agent/src/tools/gh-common.ts:115

 * can never be redirected: with `GH_HOST` set elsewhere, even a github.com
 * checkout keeps its host.
 */
export function repoFromUrl(value: string | undefined): string | undefined {
	const match = REPO_URL_PATTERN.exec(value?.trim() ?? "");
	if (!match) return undefined;
	const host = match[1].toLowerCase();
	const slug = `${match[2]}/${match[3]}`;
	return host === defaultGhHost() ? slug : formatRepoRef(host, slug);
}

export const PR_URL_PATTERN = /^https:\/\/([^/]+)\/([^/]+\/[^/]+)\/pull\/(\d+)(?:\/.*)?$/;
export const ISSUE_URL_PATTERN = /^https:\/\/([^/]+)\/([^/]+\/[^/]+)\/issues\/(\d+)(?:\/.*)?$/;

export async function requireCurrentGitBranch(cwd: string, signal?: AbortSignal): Promise<string> {
	const repo = vcs.git(cwd);
	const branch = repo ? await repo.currentBranch(signal).catch(() => null) : null;
	if (!branch) {
		throw new ToolError("Current git branch is unavailable. Pass `branch` or `run` explicitly.");
	}

	return branch;
}

export async function requireCurrentGitHead(cwd: string, signal?: AbortSignal): Promise<string> {
	const repo = vcs.git(cwd);
	const headSha = repo ? await repo.headSha(signal).catch(() => null) : null;
	if (!headSha) {
		throw new ToolError("Current git HEAD is unavailable. Pass `run` explicitly.");
	}

	return headSha;
}

export function formatAuthor(author: GhUser | null | undefined): string | undefined {
	if (!author) return undefined;
	if (author.login) return `@${author.login}`;

View on GitHub (pinned to 9690622007)

Solutions

  1. Run the tool from inside a git repository with an active branch.
  2. Pass the branch explicitly via the `branch` option (or a `run` URL that encodes it).
  3. Verify git is installed and the directory has a .git (or parent repo) — check `git rev-parse --is-inside-work-tree`.

Example fix

// before
const branch = await localBranch({ cwd });
// after
const branch = await localBranch({ cwd, branch: "feature/x" });
Defensive patterns

Strategy: validation

Validate before calling

import { $ } from "bun";
const inside = await $`git rev-parse --abbrev-ref HEAD`.cwd(cwd).quiet().nothrow();
if (inside.exitCode !== 0) {
  // pass branch explicitly or move to a repo
}

Try / catch

try {
  const branch = await localBranch({ cwd });
} catch (err) {
  if (err instanceof ToolError && err.message.includes("Current git branch is unavailable")) {
    return localBranch({ cwd, branch: explicitBranch });
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling localBranch() or executeRunWatch() in a directory that is not a git repo, or where `git rev-parse --abbrev-ref HEAD`-style lookup fails or returns null (detached HEAD flows in some wrappers, bare repo, git missing).

Common situations: Running the gh pr/pull tool from a non-repo directory; a detached HEAD state; corrupted or missing git binary; CI checkouts without a branch ref.

Related errors


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