can1357/oh-my-pi · error · GitCommandError

GitCommandError: git branch -m failed (nonzero exit)

Error message

GitCommandError: git branch -m failed (nonzero exit)

What it means

rename_workspace_branch shells out to `git branch -m <old> <new>` inside the worktree and raises GitCommandError when git exits nonzero. The most common cause is the target branch name already existing locally — git refuses to rename over an existing branch. Other causes include a corrupt or locked repository and missing git binary permissions in slot-restricted environments.

Source

Thrown at python/robomp/src/sandbox.py:208

    new_branch = f"farm/{parts[1]}/{new_slug}"
    if new_branch == workspace.branch:
        return new_branch
    if pr_number is not None:
        log.warning(
            "rename_workspace_branch skipped: PR #%d already tracks %r; refusing to rename to %r",
            pr_number,
            workspace.branch,
            new_branch,
        )
        return workspace.branch
    proc = _safe_run(
        ["git", "branch", "-m", workspace.branch, new_branch],
        cwd=workspace.repo_dir,
        env=_git_env_for_repo(workspace.repo_dir),
        **_slot_subprocess_kwargs(slot_uid),
    )
    if proc.returncode != 0:
        raise GitCommandError(
            ["git", "branch", "-m", workspace.branch, new_branch],
            proc.returncode,
            proc.stdout,
            proc.stderr,
        )
    _share_git_metadata_with_slots(workspace.repo_dir, slot_uid)
    workspace.branch = new_branch
    return new_branch


# ---------- GitTransport (transport abstraction over clone/fetch/push) ----------


class GitTransport(Protocol):
    """Pluggable remote-facing git operations.

    Two implementations ship in-tree:
    - `LocalGitTransport`: in-process git with PAT injected per invocation.

View on GitHub (pinned to 9690622007)

Solutions

  1. Check stderr in the exception for 'branch already exists'; if so, verify the existing branch is stale and delete it (`git branch -D farm/<hex>/<slug>`) or pick a different slug.
  2. Call git branch --list `farm/<hex>/*` first and choose a slug that does not collide.
  3. Retry once — transient lock contention (index.lock) usually clears; the event queue will retry the task.
  4. Inspect `git fsck` / stale `.git/worktrees` state if failures persist across all slugs.

Example fix

# before
try:
    rename_workspace_branch(ws, slug)
except GitCommandError:
    pass  # swallowed, state now inconsistent
# after
try:
    rename_workspace_branch(ws, slug)
except GitCommandError as e:
    if b"already exists" in (e.stderr or b""):
        slug = f"{slug}-{int(time.time())}"  # pick a fresh slug
        rename_workspace_branch(ws, slug)
    else:
        raise
Defensive patterns

Strategy: try-catch

Validate before calling

probe = subprocess.run(["git", "branch", "--list", new_branch], cwd=ws.repo_dir, capture_output=True)
branch_taken = bool(probe.stdout.strip())

Try / catch

try:
    rename_workspace_branch(ws, slug)
except GitCommandError as e:
    if b"already exists" in (e.stderr or b""):
        slug = f"{slug}-{secrets.token_hex(2)}"  # disambiguate and retry
        rename_workspace_branch(ws, slug)
    else:
        raise

Prevention

When it happens

Trigger: Renaming to a slug whose resulting branch `farm/<hex>/<slug>` already exists in the pool (e.g. a previous workspace or retry used the same slug); git lock contention from a concurrent worktree operation in the shared clone pool; repository corruption after a crashed git process.

Common situations: Re-running an issue after a partial failure left the target branch behind; the agent or operator picking a slug that collides with an earlier attempt; slot-uid sandboxing denying the subprocess access to the shared refs.

Related errors


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