can1357/oh-my-pi · error · GitCommandError

GitCommandError: git worktree prune failed (nonzero exit)

Error message

GitCommandError: git worktree prune failed (nonzero exit)

What it means

When `git worktree add` fails, _worktree_add deletes the partially created repo_dir and attempts `git worktree prune` to clean the pool's stale worktree registrations. If the prune itself fails, its GitCommandError is chained from the original add error and raised — signaling the pool's worktree metadata is in a bad state that automatic cleanup could not fix.

Source

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

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:
        shutil.rmtree(repo_dir, ignore_errors=True)
        pruned = _safe_run(["git", "worktree", "prune"], cwd=pool)
        if pruned.returncode != 0:
            raise GitCommandError(
                ["git", "worktree", "prune"], pruned.returncode, pruned.stdout, pruned.stderr
            ) from add_err
        raise


_SHARED_OMP_GID = 2000


def _slot_permissions_active(slot_uid: int | None) -> bool:
    return slot_uid is not None and platform.system() == "Linux" and os.geteuid() == 0


def _slot_pids(slot_uid: int, proc_root: Path = Path("/proc")) -> tuple[int, ...]:
    """Return non-zombie process ids owned by the slot UID.

    Debian's slim image does not include procps/pkill. Reading `/proc` keeps
    slot cleanup self-contained and avoids adding a runtime package only for
    this one operation.

View on GitHub (pinned to 9690622007)

Solutions

  1. Fix pool metadata: run `git worktree prune -v` manually in the pool clone and inspect `.git/worktrees/` for corrupt entries; delete bogus subdirectories.
  2. Check permissions/ownership of the pool directory (slot_uid GID sharing) — prune must be able to write the pool's .git.
  3. Remove the stale repo_dir and the whole workspace root, then retry so ensure_clone/ensure_workspace rebuild state.
  4. Escalate to recreating the pool clone (delete pool dir; ensure_clone re-clones) if metadata stays corrupt.

Example fix

# before
# event stuck failing with chained prune error
# after
# operator recovery inside the pool
subprocess.run(["git", "worktree", "prune", "-v"], cwd=pool)
shutil.rmtree(ws_root, ignore_errors=True)
ws = manager.ensure_workspace(...)  # rebuilds clean
Defensive patterns

Strategy: try-catch

Validate before calling

chk = subprocess.run(["git","worktree","prune","--dry-run"], cwd=pool, capture_output=True)
metadata_ok = chk.returncode == 0

Try / catch

try:
    ws = manager.ensure_workspace(...)
except GitCommandError as e:
    if "worktree prune" in str(getattr(e, 'cmd', '')):
        alert_operator_pool_corrupt(pool)  # needs manual .git/worktrees repair
    else:
        schedule_retry(event)

Prevention

When it happens

Trigger: ensure_workspace / ensure_release_workspace hitting a worktree add failure (existing dir, taken branch) where the follow-up `git worktree prune` also exits nonzero — typically because the pool clone's .git/worktrees metadata is corrupt, the pool dir was concurrently mutated, or permissions/locks block the prune.

Common situations: A previous git process crashed mid-worktree-registration leaving malformed .git/worktrees entries; the shared pool clone was modified by hand or by another tool; running with a slot_uid whose filesystem permissions cannot write the pool metadata.

Related errors


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