can1357/oh-my-pi · error · GitCommandError
GitCommandError(cmd, proc.returncode, proc.stdout, proc.stde
Error message
GitCommandError(cmd, proc.returncode, proc.stdout, proc.stderr)
What it means
`_check` inspects a completed `git` subprocess and raises `GitCommandError(cmd, returncode, stdout, stderr)` whenever the exit code is non-zero. This is the library's single generic git-failure path: the exception carries the exact command, git's exit code, and both (credential-redacted) output streams, so the real cause is in `proc.stderr` on the exception.
Source
Thrown at python/robomp/src/git_ops.py:287
)
except subprocess.TimeoutExpired as exc:
# `subprocess.run` already kills the direct child when the timeout
# fires, but we explicitly re-raise as `GitCommandError` so callers
# don't have to special-case `TimeoutExpired` alongside the regular
# non-zero-exit error path. 124 mirrors GNU `timeout`.
stdout = redact_credentials(exc.stdout or "") if isinstance(exc.stdout, str) else ""
stderr_msg = f"git timed out after {effective_timeout:.0f}s: {' '.join(_redacted_cmd(cmd))}"
raise GitCommandError(cmd, 124, stdout, stderr_msg) from exc
if proc.stdout:
proc.stdout = redact_credentials(proc.stdout)
if proc.stderr:
proc.stderr = redact_credentials(proc.stderr)
return proc
def _check(proc: subprocess.CompletedProcess[str], cmd: list[str]) -> subprocess.CompletedProcess[str]:
if proc.returncode != 0:
raise GitCommandError(cmd, proc.returncode, proc.stdout, proc.stderr)
return proc
def _git_dir(repo_dir: Path) -> Path | None:
dot_git = repo_dir / ".git"
if dot_git.is_dir():
return dot_git
if dot_git.is_file():
try:
text = dot_git.read_text(encoding="utf-8").strip()
except OSError:
return None
prefix = "gitdir:"
if not text.startswith(prefix):
return None
git_dir = Path(text[len(prefix) :].strip())
return git_dir if git_dir.is_absolute() else (repo_dir / git_dir).resolve()
if (repo_dir / "HEAD").exists() and (repo_dir / "objects").is_dir():View on GitHub (pinned to 9690622007)
Solutions
- Read `exc.stderr` from the GitCommandError — it contains git's own diagnostic (auth failure, rejected, not found)
- Verify credentials/token scope for the remote operation
- For push rejections, `git pull --rebase` / fetch and rebase locally before pushing again
- Check network/remote availability and the exact command recorded on the exception
Example fix
// before
push(repo_dir) # GitCommandError, code unclear
// after
try:
push(repo_dir)
except GitCommandError as exc:
print(exc.cmd, exc.returncode, exc.stderr) Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path
if not (Path(repo_dir) / ".git").exists():
raise ValueError(f"{repo_dir} is not a git repository") Try / catch
try:
_check(proc, cmd)
except GitCommandError as exc:
if exc.returncode == 128 and "Authentication" in (exc.stderr or ""):
refresh_credentials(); retry()
elif exc.returncode == 1 and "rejected" in (exc.stderr or ""):
pull_rebase_then_retry()
else:
raise Prevention
- Always inspect exc.stderr — git's message names the root cause
- Keep tokens/credentials fresh and scoped to the remote operation
- Fetch and rebase before pushing to avoid non-fast-forward rejections
- Validate repo URLs and remote names before invoking git
When it happens
Trigger: Any git invocation checked by `_check` failing: clone of a nonexistent/unauthorized repo, fetch_prune against a dead remote, push rejected (non-fast-forward, protected branch, permissions), fetch_pr_head for a missing PR ref.
Common situations: Expired/insufficient GitHub token, network DNS failure, remote branch deleted, merge conflict-ish non-fast-forward push, repository URL typo.
Related errors
- git timed out after {effective_timeout:.0f}s: {' '.join(_red
- GitCommandError(["git", *args], proc.returncode, proc.stdout
- git cat-file returned {len(lines)} lines, expected {len(CACH
- timeout reading origin url
- GitCommandError: git branch -m failed (nonzero exit)
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/d961c2a663772c78.
Report an issue: GitHub.