can1357/oh-my-pi · error · GitCommandError

GitCommandError: git command failed (nonzero exit)

Error message

GitCommandError: git command failed (nonzero exit)

What it means

Generic failure path of _run(): when the wrapped git subprocess exits with any nonzero code (other than the timeout sentinel 124), a GitCommandError is raised carrying the command, exit code, stdout and stderr. It is the sandbox's way of surfacing 'git said no' with full output so callers (and the event's last_error) can diagnose the specific git failure.

Source

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

    cmd: list[str],
    *,
    cwd: Path | None = None,
    timeout: float | None = _DEFAULT_SANDBOX_SUBPROCESS_TIMEOUT,
) -> subprocess.CompletedProcess[str]:
    """Legacy raising helper (still used by a sandbox test). Forwards to subprocess.run."""
    try:
        proc = subprocess.run(
            cmd,
            cwd=str(cwd) if cwd else None,
            check=False,
            capture_output=True,
            text=True,
            timeout=timeout,
        )
    except subprocess.TimeoutExpired as exc:
        raise GitCommandError(cmd, 124, "", f"git timed out after {timeout:.0f}s") from exc
    if proc.returncode != 0:
        raise GitCommandError(cmd, proc.returncode, proc.stdout, proc.stderr)
    return proc


def _worktree_add(add_cmd: list[str], *, pool: Path, repo_dir: Path) -> None:
    """Run `git worktree add`, cleaning partial state on failure.

    A worktree-add killed mid-operation (the 120s `_run` timeout surfaces as
    GitCommandError 124, or any nonzero git failure) can leave a partial
    checkout at `repo_dir` and/or a dangling pool worktree registration. Left
    behind, the event retry hits stale metadata and fails again on the same
    path. Best-effort remove the checkout and prune the pool, then re-raise so the
    retry starts from a clean path. If the prune itself fails (incl. a 124
    timeout), raise that instead — chained from the add error — since a
    dangling registration left behind is exactly what poisons the retry.
    """
    try:
        _run(add_cmd, cwd=pool)
    except GitCommandError as add_err:

View on GitHub (pinned to 9690622007)

Solutions

  1. Read exc.stderr — it names the actual git problem (e.g. 'already exists', 'already checked out', 'not a repository').
  2. For 'already exists': remove the stale worktree dir (`git worktree remove --force` or rm + `git worktree prune`) and retry.
  3. For 'already checked out': detach or remove the conflicting worktree, or pass a start point that allows a new checkout.
  4. If the pool clone itself is gone, delete the workspace root and re-run ensure_workspace to trigger a fresh clone.

Example fix

// before
ws = manager.ensure_workspace(...)  # fails: repo_dir exists from crashed run
// after
try:
    ws = manager.ensure_workspace(...)
except GitCommandError as e:
    if b"already exists" in (e.stderr or b""):
        shutil.rmtree(ws_root / "repo", ignore_errors=True)
        subprocess.run(["git", "worktree", "prune"], cwd=pool)
        ws = manager.ensure_workspace(...)
Defensive patterns

Strategy: try-catch

Validate before calling

if not (pool / ".git").exists():
    manager.ensure_clone(repo=repo, clone_url=url, default_branch=main)  # rebuild pool first

Try / catch

try:
    ws = manager.ensure_workspace(...)
except GitCommandError as e:
    stderr = e.stderr or b""
    if b"already exists" in stderr:
        shutil.rmtree(repo_dir, ignore_errors=True); subprocess.run(["git","worktree","prune"],cwd=pool); retry()
    elif b"already checked out" in stderr:
        detach_or_remove_conflicting_worktree(); retry()
    else:
        raise

Prevention

When it happens

Trigger: Any git invocation through _run failing — `git worktree add` when repo_dir already exists or the branch is checked out elsewhere, `git branch -m` collisions, ref updates refused, or 'not a git repository' if the pool clone is missing/corrupt.

Common situations: Retrying ensure_workspace for an issue whose repo_dir survived a prior crash (worktree add sees an existing directory); trying to check out a branch already checked out in another worktree; a half-deleted pool after disk cleanup.

Related errors


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